17
\$\begingroup\$

Note: This is inspired by this question by @Willbeing where task was to count the number of perfect plates of a certain length, but it's slightly different.


We call a perfect licence plate that plate whose text satisfies the following conditions:

  • It consists of characters, which can either be uppercase letters([A-Z]) or digits([0-9])
  • Summing the positions of its letters in the English alphabet, 1-indexed (i.e: A=1,B=2,...,Z=26) gives an integer n
  • Getting each chunk of digits, summing them and then multiplying all the results gives the same result, n
  • n is a perfect square (e.g: 49 (72), 16 (42))

A nearly perfect licence plate meets the conditions for a perfect licence plate, except that n is not a perfect square.


Input

A string representing the text of the licence plate, taken as input in any standard form, except for hardcoding.

Output

If the given string represents a nearly perfect licence plate, return a truthy value (e.g: True / 1), otherwise return a falsy value (e.g: False / 0). Any standard form of output is accepted while taking note that this loopholes are strictly forbidden.


Examples

licence plate -> output A1B2C3 -> 1 A + B + C = 1 + 2 + 3 = 6 1 * 2 * 3 = 6 6 is not a perfect square, 6 = 6 => nearly perfect plate 01G61 -> 1 (0 + 1) * (6 + 1) = 7 G = 7 7 is not a perfect square, 7 = 7 => nearly perfect plate 11BB2 -> 0 (1 + 1) * 2 = 4 B + B = 2 + 2 = 4 4 = 4, but 4 is the square of 2 => perfect license plate (not what we want) 67FF1 -> 0 (6 + 7) * 1 = 13 F + F = 6 + 6 = 12 12 != 13 => not perfect at all! 

Scoring

This is , so the shortest answer in bytes wins!

\$\endgroup\$
5
  • \$\begingroup\$ popularity-contest \$\endgroup\$ Commented Apr 8, 2017 at 15:34
  • \$\begingroup\$ I think this would be better as code-golf. \$\endgroup\$ Commented Apr 8, 2017 at 15:35
  • \$\begingroup\$ Let me make sure I understand this. We only output truthy if the licence plate is perfect and n is not a perfect square? \$\endgroup\$ Commented Apr 8, 2017 at 16:00
  • \$\begingroup\$ @mathjunkie Yes. TL;DR: only if the licence is nearly perfect (P.S sorry for the late response) \$\endgroup\$ Commented Apr 8, 2017 at 16:12
  • 2
    \$\begingroup\$ Before anyone does s/licence/license/ig on this, be aware that "licence" is the correct spelling in British English (as well as English in other parts of the world). \$\endgroup\$ Commented Apr 8, 2017 at 17:00

8 Answers 8

7
\$\begingroup\$

Jelly, 29 28 30 bytes

+1 byte to fix a bug spotted by ChristianSievers (incorrectly dealing with substrings of only zeros) +1 byte to fix false positives for "0", "00", ... found during above fixing (0 is a perfect square).

i@€ØAS;Ʋ$ e€ØAœpV€€LÐfS€P;0⁼Ç 

Try it online!, or run tests

How?

i@€ØAS;Ʋ$ - Link 1: [letter-sum, letter-sum is perfect square?]: plate i@€ - index of €ach char in plate [reversed @rguments] (1-based, 0 otherwise) in: ØA - uppercase alphabet S - sum $ - last two links as a monad: ; - concatenate with: Ʋ - is square? e€ØAœpV€€LÐfS€P;0⁼Ç - Main link: plate e.g. "11BB2" œp - partition plate at truthy values of: e€ - is in? for €ach char in plate: ØA - uppercase alphabet [['1','1'],[''],['2']] V€€ - evaluate for €ach for €ach [[1,1],[],[2]] Ðf - filter keep: L - length [[1,1],[2]] S€ - sum each [2,2] P - product 4 ;0 - concatenate a zero [4,0] Ç - last link (1) as a monad (taking plate) [4,1] ⁼ - equal? (non-vectorising) 0 
\$\endgroup\$
3
  • \$\begingroup\$ Wow, genius Jelly solution! \$\endgroup\$ Commented Apr 8, 2017 at 16:31
  • \$\begingroup\$ What about 11AA0? \$\endgroup\$ Commented Apr 9, 2017 at 14:05
  • \$\begingroup\$ @ChristianSievers, good catch. Fixed along with another, kind of related, bug and extended the test suite. \$\endgroup\$ Commented Apr 9, 2017 at 17:16
7
\$\begingroup\$

MATL, 36 34 33 35 bytes

3Y432YXU"@V!Usvp]GlY2&msy=wtQ:qUm~v 

Try it at MATL Online

Explanation

 % Implicitly grab input as a string 3Y4 % Push the predefined literal '[A-Za-z]+' to the stack 32 % Push the literal 32 to the stack (ASCII for ' ') YX % Replace the matched regex with spaces (puts a space in place of all letters) U % Convert the string to a number. The spaces make it such that each group of % of consecutive digits is made into a number " % For each of these numbers @V!U % Break it into digits s % Sum the digits v % Vertically concatenate the entire stack p % Compute the product of this vector ] % End of for loop G % Explicitly grab the input again lY2 % Push the predefined literal 'ABCD....XYZ' to the stack &m % Check membership of each character in the input in this array and % return an array that is 0 where it wasn't a letter and the index in 'ABC..XYZ' % when it was a letter s % Sum the resulting vector y % Duplicate the product of the sums of digits result = % Compare to the sum of letter indices result w % Flip the top two stack elements Q % Add one to this value (N) t: % Duplicate and compute the array [1...N] q % Subtract 1 from this array to yield [0...N-1] U % Square all elements to create all perfect squares between 1 and N^2 m~ % Check to ensure that N is not in the array of perfect squares v % Vertically concatenate the stack. % Implicitly display the truthy/falsey result 
\$\endgroup\$
2
  • \$\begingroup\$ Yields false positives for plates consisting of only zeros, e.g. '0' or '00' (FWIW I just fixed that in my code too). \$\endgroup\$ Commented Apr 9, 2017 at 17:35
  • 1
    \$\begingroup\$ @JonathanAllan Updated. \$\endgroup\$ Commented Apr 10, 2017 at 13:10
6
\$\begingroup\$

Python 2, 120 118 bytes

s=t=p=0;r=1 for n in input(): h=int(n,36) if h>9:s+=h-9;r*=t**p p=h<10;t=(t+h)*p print(s==r*t**p)&(int(s**.5)**2<s) 

Try it online!

Interprets each character as a number in base-36 (h). Converts to decimal and adds to the sum if h>9 (meaning it's a letter), otherwise adds to a variable which gets multiplied to form the running product later.

\$\endgroup\$
4
\$\begingroup\$

Perl 5, 80 bytes

79 bytes of code + -p flag.

$.*=eval s/./+$&/gr for/\d+/g;$t-=64-ord for/\pl/g;$_=$.==$t&&($.**.5|0)**2!=$. 

Try it online!

$.*=eval s/./+$&/gr for/\d+/g; multiplies the sums of consecutive digits. (I'm using $. because it's initial value is 1, which mean it's the neutral element for multiplication). More precisely, for each chunk of digits (for/\d+/g), s/./+$&/gr places a + before each digit, then the string is evaluated, and multiplied with the current product.
Secondly, $t-=64-ord for/\pl/g; sums in $t each letter (for/\pl/g). (ord return the ascii code for the letter, and 64-.. makes it be between 1 and 26.
Finally, $.==$t checks that both values are the same, and ($.**.5|0)**2!=$. that it's nor a perfect square.

\$\endgroup\$
4
\$\begingroup\$

Python 2, 267 207 bytes

Saved 60 bytes thanks to ovs

import re def g(l):a=reduce(lambda a,b:a*b,[sum(map(int,list(i)))for i in re.sub(r'\D',' ',l).split()],1);return a==sum(sum(k)for k in[[ord(i)-64for i in x]for x in re.sub(r'\d',' ',l).split()])and a**.5%1>0 

Function with usage: print(g('A1B2C3'))

Try it online!

\$\endgroup\$
1
4
\$\begingroup\$

Python 3, 163 156 155 164 161 bytes

from math import* m=1;s=t=p=0 for x in input(): try:t+=int(x);p=1 except:m*=[1,t][p];p=t=0;s+=ord(x.upper())-64 if p:m*=t print(m==s and sqrt(m)!=int(sqrt(m))) 

Try it online!

  • saved 7 bytes thanks to Jonathan and Shooqie
  • saved 1 byte: Also Fixed the false positive issue. Thanks to Jonathan for pointing it out!
  • added 11 bytes: Previous edit was wrong(the multiplication of sum of digit was going on in an unwanted loop)
\$\endgroup\$
4
  • 1
    \$\begingroup\$ from math import* is shorter \$\endgroup\$ Commented Apr 9, 2017 at 17:22
  • 1
    \$\begingroup\$ You don't need a, just use for x in input():. You can have false positives for plates ending with a string of zeros (e.g. 11AA00), since the final m*=t is not executed. \$\endgroup\$ Commented Apr 9, 2017 at 17:29
  • 1
    \$\begingroup\$ Apparently, my code shows false positive for any string with isolated zeros in it ( 3A0B is also shown true )... Thanks for pointing that out @JonathanAllan. I will try to fix it. \$\endgroup\$ Commented Apr 10, 2017 at 3:03
  • \$\begingroup\$ Check the newer version... I have added a new flag variable 'p' to decide whether or not to multiply the sum of digits. \$\endgroup\$ Commented Apr 10, 2017 at 3:14
3
\$\begingroup\$

Retina, 143 bytes

Returns 1 for true, 0 for false

 [1-9] $* 10|01 1 S_`(\D) O` {`1(?=1*\n(1+)) $1 )2=`1+\n [J-S] 1$+ [T-Z] 2$+ T`0L`ddd 1>`\d+\n? $* ^((?(1)((?(2)\2(11)|111))|1))*\n ^(1*)\n\1$ 

Try it Online!

Explanation:

 [1-9] $* 10|01 1 

First, we replace all non-zero digits with their unary representation. We remove any zeroes with an adjacent digit so that they don't affect our unary operations

 S_`(\D) 

Split the resulting string on letters, being careful to exclude empty lines (this is a problem when two letters are consecutive AA).

 O` {`1(?=1*\n(1+)) $1 )2=`1+\n 

Sort the string lexicographically. Then repeatedly do the following:

1) Replace each 1 with the number of 1s on the following line (this mimics multiplication)

2) Remove the second line of 1s

 [J-S] 1$+ [T-Z] 2$+ T`0L`ddd 

Replace letters J-S with 1J, 1K, etc. and replace letters T-Z with 2T, 2U, etc. Then, replace each of the groups A-I, J-S, and T-Z with 1-9. We will be left with the numerical value of each letter (eg. 13 for M).

 1>`\d+\n? $* 

Convert every line but the first into unary (the first line is already in unary). Concatenate these lines. We are now left with a string of the form <product of digits>\n<sum of letters>.

 ^((?(1)((?(2)\2(11)|111))|1))*\n 

Replace a square number with the empty string. This uses the "difference tree" method.

 ^(1*)\n\1$ 

Return 1 if the two strings on either side of the \n match. Otherwise, return 0.

\$\endgroup\$
2
  • \$\begingroup\$ False positives for 11AA0, 0AA11, etc. \$\endgroup\$ Commented Apr 9, 2017 at 17:39
  • \$\begingroup\$ @JonathanAllan Thanks! It cost me 11 bytes to fix \$\endgroup\$ Commented Apr 9, 2017 at 18:32
1
\$\begingroup\$

Ruby, 87 bytes

->s{m=0 n=1 s.scan(/(\d+)|./){$1?n*=$1.bytes.sum{_1-48}:m+=$&.ord-64} m==n&&m**0.5%1>0} 

Attempt This Online!

\$\endgroup\$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.