15
\$\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\$
  • \$\begingroup\$ popularity-contest \$\endgroup\$ – lol Apr 8 '17 at 15:34
  • \$\begingroup\$ I think this would be better as code-golf. \$\endgroup\$ – Erik the Outgolfer Apr 8 '17 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\$ – math junkie Apr 8 '17 at 16:00
  • \$\begingroup\$ @mathjunkie Yes. TL;DR: only if the licence is nearly perfect (P.S sorry for the late response) \$\endgroup\$ – Mr. Xcoder Apr 8 '17 at 16:12
  • 1
    \$\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\$ – Mego Apr 8 '17 at 17:00
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\$
  • \$\begingroup\$ Wow, genius Jelly solution! \$\endgroup\$ – Mr. Xcoder Apr 8 '17 at 16:31
  • \$\begingroup\$ What about 11AA0? \$\endgroup\$ – Christian Sievers Apr 9 '17 at 14:05
  • \$\begingroup\$ @ChristianSievers, good catch. Fixed along with another, kind of related, bug and extended the test suite. \$\endgroup\$ – Jonathan Allan Apr 9 '17 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\$
  • \$\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\$ – Jonathan Allan Apr 9 '17 at 17:35
  • 1
    \$\begingroup\$ @JonathanAllan Updated. \$\endgroup\$ – Suever Apr 10 '17 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\$
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\$
  • 1
    \$\begingroup\$ from math import* is shorter \$\endgroup\$ – shooqie Apr 9 '17 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\$ – Jonathan Allan Apr 9 '17 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\$ – officialaimm Apr 10 '17 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\$ – officialaimm Apr 10 '17 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\$
  • \$\begingroup\$ False positives for 11AA0, 0AA11, etc. \$\endgroup\$ – Jonathan Allan Apr 9 '17 at 17:39
  • \$\begingroup\$ @JonathanAllan Thanks! It cost me 11 bytes to fix \$\endgroup\$ – math junkie Apr 9 '17 at 18:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.