25
\$\begingroup\$

5 Years ago, this happened, and then it became sort of a meme.

Challenge

The Challenge today is, to check if a "magic square" is a valid parker square.
What is a Real Magic square?

  • All the numbers must be natural or sometimes 0
  • The sum of rows, columns and diagonals must be same.
  • There must be no repeating numbers

What Matt tried to achieve is a real magic square but with all the numbers being squares.
But what he did is a semi-magic square, sometimes called The Parker Square.

What is a valid parker square (rules made by me)?

  • It must be a \$3\times3\$ "magic square"
  • There must be at least one number that appear twice in the square
  • The rows and columns must add up to the same number
  • At least one diagonal must add up to the same number too.
  • Each number must be the square of an integer

Rules

  • Input must be given in a form of a list (flat or 2-dimensional), or just 9 inputs from top left to bottom right
  • Input is guaranteed to represent a \$3×3\$ square
  • Output must be a Boolean, 1 or 0, no output or some output
  • Standard Loopholes apply
  • This is , so the shortest code in each language wins!

Examples

Classic Parker Square:
In: [841, 1, 2209, 1681, 1369, 1, 529, 1681, 841]
Out: True

0-Square
In: [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
Out: 1

Mirrored Square:
In: 4, 9, 1, 9, 1, 9, 1, 9, 4
Out: 0

Random Square:
In: 1, 2, 4, 3, 4, 9, 8, 9, 0
Out: False

Real Magic Square:
In: [[8, 1, 6], [3, 5, 7], [4, 9, 2]]
Out:

Pythagorean triple (by Arnauld):
In: [25, 0, 0, 0, 16, 9, 0, 9, 16]
Out: false

Non integer (Suggested by Luis):
In: [841.45, 1, 2209, 1681, 1369, 1, -529, 1681, 841]
Out: false

Almost real magic square of squares (Suggested by Jonathan):
In: [[16129, 2116, 3364], [4, 12769, 8836], [5476, 6724, 9409]]
Out: 0

Disclaimer: I put magic square in quotes, because most people don't think it is a magic square if the numbers repeat. But it doesn't mean it is easy to make a "magic square" with only a few numbers repeating, all squares and on of the diagonals working. Good work Matt!

\$\endgroup\$
4
  • \$\begingroup\$ Sandbox \$\endgroup\$
    – math
    Jun 12 at 11:22
  • 1
    \$\begingroup\$ For everyone: Please ask questions is this chat room. Sorry, idk know to change the title. \$\endgroup\$
    – math
    Jun 12 at 17:37
  • \$\begingroup\$ You misspelled "happened". +1 for the challenge though. \$\endgroup\$ Jun 24 at 9:34
  • \$\begingroup\$ @StackMeter Thanks! That one downvote on my question must have been matt parker. \$\endgroup\$
    – math
    Jun 24 at 9:36
8
\$\begingroup\$

05AB1E, 25 23 bytes

-1 byte thanks to Grimmy!

‚εÅ\ªIø«OË}àI˜ÐÙÊsŲPP

Try it online! or Try all cases!

Commented:

‚               # pair the input with its reverse
  ε        }     # map over each of them:
   Å\            #   take the main diagonal
     ª           #   append this to the input
      Iø         #   push the input transposed
        «        #   and concatenate this to the list
         O       #   sum rows, columns and the diagonal
          Ë      #   are all sums equal?
            à    # is one of the two results a 1?

I˜               # push the input and flatten it
  Ð              # triplicate
   ÙÊ            # does the uniquified flat input not equal the flat input?
     s           # swap to flattened input
      Ų         # for every number: is it a square integer?
        P        # are all square?

P                # take the product (AND reduction) of all results
\$\endgroup\$
6
  • \$\begingroup\$ Does this test that the input only contains integers? (Just asking) \$\endgroup\$
    – Luis Mendo
    Jun 12 at 16:14
  • \$\begingroup\$ @LuisMendo Ų (is square?) checks if the input is an integer as well. \$\endgroup\$
    – ovs
    Jun 12 at 17:05
  • \$\begingroup\$ Ë (all equals) can be used both to check that all sums are equal, and to check for duplicates in the input (it’s shorter than either δQ or ÙÊ) \$\endgroup\$
    – Grimmy
    Jun 12 at 17:13
  • \$\begingroup\$ Thanks. Your comment “for every integer: is it a square number?” suggested that you only considered integers for the squareness test \$\endgroup\$
    – Luis Mendo
    Jun 12 at 17:14
  • 1
    \$\begingroup\$ 23 bytes \$\endgroup\$
    – Grimmy
    Jun 12 at 17:17
6
\$\begingroup\$

Vyxal, 34 bytes

Ṙ"vÞDƛh∑;??øTJv∑$Mƛf≈;a?fDU≠$∆²AWΠ

Try it Online!

Bug fixes make it even messier.

\$\endgroup\$
0
6
\$\begingroup\$

JavaScript (ES7),  129  120 bytes

Expects a flat array of 9 values. Returns 0 for Parker, or 1 for non-Parker.

a=>new Set([A,B,C,D,E,F,G,H,I]=a).size>8|a.some(x=>x**.5%1)|[D+E+F,G+H+I,A+D+G,B+E+H].some(x=>x-A-B-C)|E+I!=B+C&E+G!=A+B

Try it online!

Or 117 bytes if we can just return truthy / falsy values.

How?

We split the input array into 9 distinct variables.

A B C
D E F
G H I

At the same time, we turn the input array into a set and check its size. If it's greater than \$8\$, then all values are distinct and this is not a Parker square.

new Set([A, B, C, D, E, F, G, H, I] = a).size > 8

We test whether at least one of the values is not a square:

a.some(x => x ** .5 % 1)

We test the sum of the values in the 2nd row, 3rd row, 1st column and 2nd column. If one of them is not equal to the sum of the values in the 1st row, this is not a Parker square.

[D + E + F, G + H + I, A + D + G, B + E + H].some(x => x - A - B - C)

Note: We don't have to test the 3rd column. It's trivial to prove that we have \$F+I=A+B\$ (and therefore \$C+F+I=A+B+C\$) if all other sums described above are correct.

Finally, we test whether both diagonals have an invalid sum:

E + I != B + C & E + G != A + B
\$\endgroup\$
3
  • \$\begingroup\$ I think you mean 9... \$\endgroup\$
    – emanresu A
    Jun 13 at 6:18
  • \$\begingroup\$ @Ausername No. If the set's size > 8, it necessarily has 9 elements in it, meaning no duplicates. \$\endgroup\$
    – user100690
    Jun 13 at 9:24
  • \$\begingroup\$ @ophact It was another typo (split the input array into 8 distinct variables). \$\endgroup\$
    – Arnauld
    Jun 13 at 9:27
6
\$\begingroup\$

R, 106 105 104 bytes

function(m,`?`=colSums)all(table(m)<2)|sd(c(?m,s<-?t(m)))|any(m^.5%%1)|sum(diag(m))-s&&sum(m[1:3*2+1])-s

Try it online!

Output is reversed*: TRUE if it is not a Parker square, FALSE otherwise.

Ungolfed code (still the right way around):

is_parker_square=
function(m){
    twice=any(table(m)-1) # some number must appear twice
    rowscols=!sd(c(rowSums(m),s<-colSums(m))) # rows & cols must have same sum
    diags=any(c(sum(diag(m)),sum(diag(m[3:1,])))==s) # at least one diag must have same sum
    squares=!any(m^.5%%1) # all numbers are squares
    twice && rowscols && diags && squares
}

*Add +5 bytes to output TRUE for a Parker square.

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

Jelly,  27  25 bytes

S;§fƑⱮ,UŒDḢ$€§ƲẸȧƲȦȧ⁸FQƑ

Parker: 0, non-Parker: 1 - just like it always seems to be! ;p

Try it online!

How?

S;§fƑⱮ,UŒDḢ$€§ƲẸȧƲȦȧ⁸FQƑ - Link: 3 by 3 matrix, M
S                         - column sums (M)
  §                       - row sums (M)
 ;                        - (column sums) concatenate (row sums)
              Ʋ           - last four links as a monad - f(M):
       U                  -   reverse each row (of M)
      ,                   -   (M) pair (reversed row version)
           $€             -   for each:
        ŒD                -     diagonals
          Ḣ               -     head
             §            -   sums -> [sum(main diagonal), sum(anti-diagonal)]
     Ɱ                    - map with:
    Ƒ                     -   is invariant under:
   f                      -     (column-and-row-sums) filter keep (diagonal-sum)
               Ẹ          - any?
                 Ʋ       - is square (vectorises across M)
                ȧ         - logical AND -> 0 or [[is r1c1 square?,...],...]
                   Ȧ      - contains no zero when flattened?
                    ȧ⁸    - logical AND with M -> 0 or M
                      F   - Flatten -> [0] or flattened M
                        Ƒ - is invariant under:
                       Q  -   deduplicate
\$\endgroup\$
4
\$\begingroup\$

J, 59 57 bytes

((<.@%:-:%:)*]>&#~.)@,*3>+/(2#.{.~:])@,1&#.,],&(2{+//.)|.

Try it online!

  • (<.@%:-:%:) All are perfect squares.
  • ]>&#~. Length of uniq is less than length (ie, has repeats)
  • The remainder first creates a single list of all 8 relevant sums (cols, rows, diagonals):
    • ],&(2{+//.)|. Get the / diagonal sum of both the input and the input with rows reversed. This gives us both diagonal sums.
    • 1&#., Prepend row sums.
    • +/..., Prepend col sums.
  • {.~:] Turn that list into a boolean list indicating which elements are not equal to the first element.
  • 2#. Interpret that result as a binary number.
  • 3> Check if it is less than 3 (will only be true if at most 1 diagonal fails to match the other sums)
\$\endgroup\$
5
  • \$\begingroup\$ The output's all one? 🤔 \$\endgroup\$
    – math
    Jun 12 at 17:41
  • \$\begingroup\$ @math That means that all test cases are passing. If you look at the test cases, you'll see some have 0 = and some have 1 = \$\endgroup\$
    – Jonah
    Jun 12 at 17:41
  • \$\begingroup\$ Oh, I see. So you're checking the output in the footer? (Never saw a language yet with one is equals for checking) \$\endgroup\$
    – math
    Jun 12 at 17:43
  • 1
    \$\begingroup\$ Right. I just glance at the footer, and if there's anything other than a 1 I know something isn't working. If it's all 1s, I'm good. Makes it easier to refactor and experiment when trying to shave down bytes. \$\endgroup\$
    – Jonah
    Jun 12 at 17:46
  • 2
    \$\begingroup\$ "Never saw a language yet with one is equals for checking" One is just the convention for boolean true. This is called "the Iverson convention," after Kenneth Iverson, the creator of J and APL. \$\endgroup\$
    – Jonah
    Jun 12 at 17:55
3
\$\begingroup\$

JavaScript (Node.js), 165 163 161 bytes

l=>l.some(e=>e**.5%1)|(I=([c,i=3])=>l[c]+l[c+=i]+l[c+=i]!=l[0]+l[1]+l[2])([0,4])&I([2,2])|[[0],[1],[2],[3,1],[6,1]].some(I)|l.every(e=>l.map(g=>z+=g==e,z=0)|z<2)

Try it online!

This feels too long.

Outputs 1 for non-Parker and 0 for Parker.

+38 to fix bug

\$\endgroup\$
2
  • \$\begingroup\$ Isn't the 0-square supposed to be a Parker square by the rules? \$\endgroup\$ Jun 12 at 12:39
  • \$\begingroup\$ Output is reversed. I'll edit that \$\endgroup\$
    – user100690
    Jun 12 at 12:40
3
\$\begingroup\$

MATL, 30 bytes

t!GXdGPXd&hsdXB2>GX^1\=Gun9<vA

Input is a 3×3 matrix. Output is 1 if it is a Parker square, 0 if not.

Try it online! Or verify all test cases.

Explanation

t!    % Implicit input: 3×3 matrix. Duplicate
GXd   % Push input again. Diagonal as a column vector
GPXd  % Push input, flip vertically. Diagonal as a column vector (this is the
      % anti-diagonal of the input)
&h    % Concatenate everything horizontally. This gives a 8×3 matrix whose
      % columns are: the 3 columns of the input, the 3 rows of the input, the
      % diagonal and the anti-diagonal
s     % Sum of eah column. Gives a row vector of length 8 (*)
d     % Consecutive differences. Gives a row vector of length 7
XB    % Convert from binary expansion to number. This treats nonzero values in 
      % the input as 1
2>    % Is it greater than 3? (**) This gives false if and only if all entries
      % in (*) are equal except perhaps the last or second-to-last, but not both 
      % (The result will be false for a valid input)
GX^   % Push input. Square root of each entry
1\    % Modulo 1. (***) (All entries give 0 for a valid input)
=     % Equal? Since the modulus is always less than 1, equality means that all
      % entries in (***) were 0, as was (**). (This gives a matrix containing
      % only true for a valid input)
Gun   % Push input again, unique elements as a row vector, number of elements
9<    % Less than 9? (True for a valid input)
v     % Concatenate everything into a column vector
A     % All: gives true if all entries are true. Implicit display
\$\endgroup\$
2
\$\begingroup\$

Python 3.8 (pre-release), 154 144 bytes

lambda a:1-any([len({*a})>8,{(s:={sum(a[i%7:i%5*3:i%4])-a[4]for i in b"\r@@@+?"}).pop()}-{a[0]+a[8],a[2]+a[6]},s,sum(i<0 or i**.5%1for i in a)])

@ represents unprintables chars

Outputs 1 for Parker, 0 for not Parker

Try it online!

A pretty messy solution ^^

How it works:

  • 1-any([...]) will return 1 if all elements are False
  • len({*a})>8 length of the set of a, returne True if equal to 9 (no duplicates)
  • (s:={sum(a[i%7:i%5*3:i%4])-a[4]for i in b"\r@@@+?"}) create the set of the sums of all lines and columns (name it s). I used the impicit conversion of bytes into ints to store the values for the slices.
  • { .pop()}-{a[0]+a[8],a[2]+a[6]} remove an element of s and verify if it is equal to the sum of one diagonal. I used set substraction. If it is present, return the empty set (=> False) else, return itself (=>True)
  • s verify if s is empty (=> False if s had exactly one element before the pop)
  • sum(i<0 or i**.5%1for i in a) verify both than i is positive and i is a square. If any i is lower than 0, i<0 will be True and the sum will no longer be nul. If any i is not a sqare, i**.5 (sqrt(i)) will have a decimal part and i**.5%1 won't be nul.
\$\endgroup\$
1
  • \$\begingroup\$ Nice idea with the set to check for duplicates! \$\endgroup\$
    – math
    Jun 14 at 18:28

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.