27
\$\begingroup\$

This is my first question here, so any suggestions in the comments would be appreciated! Thanks ;)

Introduction

One very common strategy for the 2048 game is never ever swiping down. This positions all the big numbers at the top, and the lower ones in the bottom. So, if you apply this strategy correctly, your board will always match the following pattern:

The pattern to check for / Your task

Your submission should be either a full program or a function which returns a truthy value if the board can be described like this: Going down each column of the board, the first number should be the highest of the column, the second number should be less than or equal to the first number, etc. A good 2048-board is defined as a board where the highest numbers are all on the top. This is code-golf, so the shortest Code per language (in bytes) wins.

I/O

The input can be taken in any appropriate way, for example an array of 4 arrays, each containing 4 numbers, or an array of 16 numbers. In total, it will be always 16 numbers, representing the 4x4 board The output should be a truthy value of the input is a "good 2048-board", and a falsy value otherwise.

Examples

Truthy:

|-------------------|
| 16 |    | 64 |  8 |
|-------------------|
|  8 |    | 32 |  8 |
|-------------------|
|  4 |    | 32 |  2 |
|-------------------|
|  2 |    |    |    |
|-------------------|


|-------------------|
| 16 | 128| 64 | 32 |
|-------------------|
|  8 | 128| 32 |  8 |
|-------------------|
|  4 | 16 |  8 |  2 |
|-------------------|
|  4 |    |    |    |
|-------------------|

Falsy:

|-------------------|
| 16 |    | 64 |  8 |
|-------------------|
|  8 |    | 32 | 16 |
|-------------------|
| 32 |    | 128|  2 |
|-------------------|
|  2 |    |    |    |
|-------------------|


|-------------------|
| 16 | 128| 64 | 32 |
|-------------------|
|  8 |  32|    |  8 |
|-------------------|
|  4 | 16 |  8 |  2 |
|-------------------|
|  4 |    |    |    |
|-------------------|

Note

Look at the 2nd falsy test case: When there is an empty value (or a 0) somewhere and even when it's followed by a value which is higher than the last non-zero number, this should be falsy, because the next value after the zero would be higher than the 0 itself, which makes it invalid.

Good luck!

\$\endgroup\$
1
  • \$\begingroup\$ Comments are not for extended discussion; this conversation has been moved to chat. \$\endgroup\$ Sep 3, 2017 at 13:14

22 Answers 22

16
\$\begingroup\$

Haskell, 21 bytes

all$scanr1 max>>=(==)

Try it online!

Takes a list of columns, with empty spaces as 0.

\$\endgroup\$
5
  • \$\begingroup\$ Gives the wrong output for [[16,8,4,0],[16,0,4,4],[16,4,4,4],[16,4,4,4]]. \$\endgroup\$ Aug 1, 2017 at 13:39
  • \$\begingroup\$ @JonathanAllan It returns false as it should, your 2nd column is [16,0,4,4] which is not monotonic. Or am I missing something? \$\endgroup\$
    – Kuba
    Aug 1, 2017 at 14:07
  • \$\begingroup\$ 0 is your placeholder for an empty cell, not a value of 0. \$\endgroup\$ Aug 1, 2017 at 14:09
  • 2
    \$\begingroup\$ @Iwanttomakegames that comment was meant for you (replace "your" with "the"). \$\endgroup\$ Aug 1, 2017 at 15:12
  • \$\begingroup\$ @JonathanAllan I am sorry for all the confusion, but 0 should indeed, while representing an empty cell, count as the value 0. Empty cells should be treated like the value '0'. \$\endgroup\$
    – dv02
    Aug 1, 2017 at 16:52
10
\$\begingroup\$

05AB1E, 4 bytes

€{íQ

Try it online!

Same as my other two answers. I promise this is my last one until others have answered :)

\$\endgroup\$
9
\$\begingroup\$

APL (Dyalog), 7 4 bytes

Takes 4-by-4 matrix, using 0 for blanks, as argument.

⊢≡⌊⍀

Try it online!

⌊⍀ is the vertical cumulative minimum

 identical to

 the unmodified argument?

\$\endgroup\$
1
  • \$\begingroup\$ Amazing golf! (I expected that from someone who works for Dyalog and has programmed APL for a long time). And, yes, MY does have a lot of APL symbols, though they're not APL symbols. Alpha, Iota, Omega are all greek, not APL technically. They came to mind first when thinking of one-character commands. Hence MY's increment and decrement are Jelly's, because that came to mind first. (Just to notify you, I'm suspended from chat, hence the response here.) \$\endgroup\$
    – Adalynn
    Aug 2, 2017 at 23:45
7
\$\begingroup\$

R (+pryr), 23 bytes

pryr::f(all(diff(x))<1)

Which evaluates to the function

function (x) 
all(diff(x)) < 1

Which takes a matrix as input:

     [,1] [,2] [,3] [,4]
[1,]   16    0   64    8
[2,]    8    0   32    8
[3,]    4    0   32    2
[4,]    2    0    0    0

When given a matrix, diff automatically calculates the differences within rows (surprisingly. I didn't know of this feature until I tried it for this challenge).

     [,1] [,2] [,3] [,4]
[1,]   -8    0  -32    0
[2,]   -4    0    0   -6
[3,]   -2    0  -32   -2

None of these values can be 1 or higher in a good board, so we test for <1 and see if all values of the matrix comply.

     [,1] [,2] [,3] [,4]
[1,] TRUE TRUE TRUE TRUE
[2,] TRUE TRUE TRUE TRUE
[3,] TRUE TRUE TRUE TRUE

[1] TRUE
\$\endgroup\$
7
\$\begingroup\$

Jelly, 4 bytes

Ṣ€U⁼

Try it online!

Input as an array of columns. Works with arbitrary-sized grids.

\$\endgroup\$
16
  • \$\begingroup\$ What is the representation of an empty cell? (e.g. 3rd col of 2nd falsey test case) - "in total it will be always 16 numbers". It would work with zeros if you filter them out first. \$\endgroup\$ Aug 1, 2017 at 12:16
  • \$\begingroup\$ @JonathanAllan According to the specs, I think this is valid too \$\endgroup\$
    – hyper-neutrino
    Aug 1, 2017 at 14:22
  • \$\begingroup\$ Yet that will now fail my suggested test case returning 0 rather than 1. \$\endgroup\$ Aug 1, 2017 at 14:35
  • \$\begingroup\$ @JonathanAllan How do you filter in Jelly ._. I'd expect this to work but ḟ0 doesn't work \$\endgroup\$
    – hyper-neutrino
    Aug 1, 2017 at 15:05
  • 1
    \$\begingroup\$ @DirtyDev That's alright, we're here to enjoy the challenges and help new users get used to this place :) I hope you're enjoying the community \$\endgroup\$
    – hyper-neutrino
    Aug 1, 2017 at 17:35
6
\$\begingroup\$

Python 3, 42 bytes

lambda l:all(x==sorted(x)[::-1]for x in l)

Try it online!

Same algorithm as my Jelly answer

\$\endgroup\$
1
5
\$\begingroup\$

JavaScript, 37 bytes

x=>''+x==x.map(v=>v.sort((x,y)=>y-x))

Call it like this:

|-------------------|
| 16 |    | 64 |  8 |
|-------------------|
|  8 |    | 32 |  8 |
|-------------------|
|  4 |    | 32 |  2 |
|-------------------|
|  2 |    |    |    |
|-------------------|

f([[8,8,2,0],[64,32,32,0],[0,0,0,0],[16,8,4,2]])

Tested on Firefox, Chrome, JavaScript Shell, and, Node.js.

\$\endgroup\$
2
  • \$\begingroup\$ Why do you turn the result into a string? (''+) \$\endgroup\$
    – Adalynn
    Aug 1, 2017 at 17:37
  • \$\begingroup\$ @Zacharý sort is mutable method, which will mutate the array. first convert to string will save a copy of the array. converting to string also make the equal operation works by (string) value instead of reference. \$\endgroup\$
    – tsh
    Aug 2, 2017 at 1:34
4
\$\begingroup\$

C# (.NET Core), 71 bytes

i=>{for(int n=3;++n<i.Length;)if(i[n]>i[n-4])return false;return true;}

Try it online!

The BORING way. Expects input flattened into a linear array.

Alternatively the explicitly forbidden way:

i=>{for(int n=3;i[++n]<=i[n-4];);}

Try it online!

Throws an IndexOutOfBoundsException to indicate true, ends normally to indicate false. I tried a version that included conversion from exception/no exception to true/false, but it ended up just as long as the regular version.

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

JavaScript, 34, 32 bytes

v=>!v.some((x,i)=>i%4&&x>v[i-1])

Call by passing in a single array containing the first column, followed by the 2nd, 3rd, and 4th.

Compares each number to the previous number except for the first number of each column and returns true if all are true.

Test

f=v=>!v.some((x,i)=>i%4&&x>v[i-1])

f([16,8,4,2,0,0,0,0,64,32,32,0,8,8,2,0])
f([16,8,4,4,128,128,16,0,64,32,8,0,32,8,2,0])
f([16,8,32,2,0,0,0,0,64,32,128,0,8,16,2,0])
f([16,8,4,4,128,32,16,0,64,0,8,0,32,8,2,0])

Edit: saved 2 bytes thanks to tsh

\$\endgroup\$
1
  • \$\begingroup\$ after some boolean transform: v=>!v.some((x,i)=>i%4&&x>v[i-1]) \$\endgroup\$
    – tsh
    Aug 3, 2017 at 7:04
3
\$\begingroup\$

Haskell, 28 bytes

all$and.(zipWith(>=)=<<tail)

There's also

all$(==)=<<sort

with 15 bytes but it requires import Data.List when working with the Prelude only. Alternatively,

all$(==)=<<Data.List.sort

with 25 bytes works in GHCI.

\$\endgroup\$
3
\$\begingroup\$

Gaia, 3 6 bytes

+3 bytes because apparently I didn't know how my language worked

ọ¦_ẏ⁇!

This is a function accepting a list of columns and leaving the result on the stack.

A few other 6 byte solutions exist including 0+¦o¦ẏ and ọ¦_ẏ¦ỵ.

Try it online!

Explanation

ọ¦      Deltas of each column
  _     Flatten
   ẏ⁇   Keep only positive numbers
     !  Negate (is it empty?)
\$\endgroup\$
4
  • \$\begingroup\$ Can't downvote, but using an operator added to the language after the challenge was posted doesn't seem fair to me.Also it seems to be forbidden by default according to this. \$\endgroup\$
    – Cinaski
    Aug 2, 2017 at 13:57
  • \$\begingroup\$ @Cinaski We've kind of moved away from that rule, as seen here. Either way, my alternative solutions only use operators that definitely existed before the challenge. \$\endgroup\$ Aug 2, 2017 at 14:01
  • \$\begingroup\$ I'll just change it to one of the others I guess \$\endgroup\$ Aug 2, 2017 at 14:02
  • \$\begingroup\$ Never mind, I was not aware of that new rule. \$\endgroup\$
    – Cinaski
    Aug 2, 2017 at 14:07
3
\$\begingroup\$

TI-BASIC, 25 bytes

Takes input as a 4x4 matrix in Ans.

For(R,1,3
*row+(-1,Ans,R+1,R
End
Ans=abs(Ans

Explanation

For(R,1,3             Loop from row 1 to 3.

*row+(-1,Ans,R+1,R    Multiply row R+1 by -1 and add it to row R in-place.
                      Effectively, this subtracts row R+1 from row R.

End                   Now the first 3 rows contain the row differences,
                      and the 4th row is non-negative assuming valid input.

Ans=abs(Ans           Check whether every element in the matrix is equal to its
                      absolute value, or in other words, contains no negative values.
\$\endgroup\$
2
\$\begingroup\$

Haskell, 41 bytes

f[x]=1>0
f(a:b:c)|a<b=1<0|1>0=f$b:c
all f

Try it online!

Defines the point-free function all f, where f determines if a list is sorted.

\$\endgroup\$
3
  • \$\begingroup\$ Darn, this beats Python by 1 byte ;P \$\endgroup\$
    – hyper-neutrino
    Aug 1, 2017 at 2:22
  • \$\begingroup\$ @HyperNeutrino Well the xnor's beats python by 21. :P \$\endgroup\$
    – Wheat Wizard
    Aug 1, 2017 at 3:17
  • \$\begingroup\$ You can also define f as f(a:b:c)=a>=b&&f(b:c) \$\endgroup\$ Aug 1, 2017 at 11:03
2
\$\begingroup\$

JavaScript (ES6), 42 bytes

Takes an array of columns; returns a (truthy) number or false.

a=>a.every(c=>c.reduce((r,n)=>r&&n<=r&&n))

JavaScript (ES6), 54 47 bytes

First attempt. Takes an array of columns; returns true or false.

a=>a.every(c=>c.slice(1).every((n,i)=>n<=c[i]))
\$\endgroup\$
1
  • \$\begingroup\$ Which value are you expecting for empty cells? \$\endgroup\$
    – Arnauld
    Aug 1, 2017 at 9:02
2
\$\begingroup\$

MATL, 4 bytes

SGX=

Try it online!

Input as an array of rows, upside down.

S       % sort columns
GX=     % compare with input
        % true if arrays are numerically equal
        % (implicit) convert to string and display
\$\endgroup\$
6
  • \$\begingroup\$ Does not work for cases that should return truthy which have zeros between column elements like this for example. \$\endgroup\$ Aug 1, 2017 at 12:29
  • \$\begingroup\$ You're right, I'm working on a solution. BTW I'm not the only one having problems with empty cells ;) \$\endgroup\$
    – Cinaski
    Aug 1, 2017 at 12:57
  • \$\begingroup\$ Yeah, I can see that. I suggested a test case for it too. Ping when fixed and you'll get an upvote from me :) \$\endgroup\$ Aug 1, 2017 at 13:02
  • \$\begingroup\$ @JonathanAllan wait, who said that it should return truthy when there are zeros between column elements? Look at my second falsy test case, an empty cell / a 0 followed by a higher value when going down is invalid. \$\endgroup\$
    – dv02
    Aug 1, 2017 at 16:27
  • \$\begingroup\$ @DirtyDev FYI with the wording originally given, and its sensible interpretation, your second falsey case would still be falsey; it's just my suggested test case would be truthy. \$\endgroup\$ Aug 1, 2017 at 16:55
2
\$\begingroup\$

Swift 4, 84 77 bytes

func f(l:[[Int]]){print(l.filter{$0.reversed()==$0.sorted()}.count==l.count)}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Dyalog APL, 21 19 15 bytes

∧/{⍵≡⍵[⍒⍵]}¨↓⍉⎕

Try it online! (modified so it will run in tryapl)

Takes input as a 2D array.

How?

  • input
  • transpose
  • 2D array => 1D vector of 1D vectors
  • { ... }¨ apply this to each member (argument ):
    • ⍵[⍒⍵] sorted descending
    • ⍵≡ equality with
  • ∧/ whether every element is 1.
\$\endgroup\$
1
2
\$\begingroup\$

Clojure, 30 bytes

(partial every? #(apply >= %))

try it online

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to PPCG, and nice first post! \$\endgroup\$
    – Adalynn
    Aug 6, 2017 at 15:33
2
\$\begingroup\$

Japt, 7 5 bytes

Takes input as a 2D array of columns. Empty cells are 0 or can be omitted if there are no other numbers in the column.

eUËnw

Try it

eUËnw     :Implicit input of 2D array U
e         :Test for equality with
 UË       :  Map U
   n      :    Sort each by
    w     :    Maximum
\$\endgroup\$
2
  • \$\begingroup\$ Nice arrangement to skip the second U. You could do nn at the end as well ;) \$\endgroup\$ Aug 1, 2017 at 13:32
  • \$\begingroup\$ I was surprised to find that omitting the second U worked in this case, @ETHproductions; I thought it would only work if the variable was the only thing to the left of the ==. I'll have to remember it for future use. \$\endgroup\$
    – Shaggy
    Aug 1, 2017 at 13:34
1
\$\begingroup\$

Java 8, 69 bytes

b->{for(int[]c:b)for(int i=0,f=1;i<3;)if(c[i]<c[++i])f=0;return f>0;}

Well, as of this writing this beats the Swift solution, so there's that! Utterly straightforward. Input is an array of integer arrays, the inner arrays being columns of the board (upper squares first). Cast to Function<int[][], Boolean>.

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

MY, 66 62 20 bytes (noncompeting)

ω⍉ω⍉A6ǵ'ƒ⇹(E8ǵ'ƒ⇹(Π←

Try it online!

The reason this is non competing is that I recently implemented 8E (≡), which is equivalent to APL .

How?

  • ω⍉ The first command line argument transposed
  • ω⍉ The first command line argument transposed
  • A6ǵ' push chr(0x6A) ( in the codepage, which sorts descending)
  • ƒ as a function, rather than a string
  • push a function that maps a popped function over each argument
  • ( apply
  • E8ǵ'ƒ⇹( the same thing, except with chr(0x8E), which is the match command ().
  • Π product
  • output with no newline

Yes, a lot of MY's symbols are exactly the same or similar to APL's. The explanation is that they came to mind when I wanted a 1-character command. (I don't know why I didn't use T for transpose)

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

Mathematica, 27 bytes

t=Thread;-t[Sort/@-t@#]==#&

Explanation:

  • Thread is a weird general transpose-like operation that happens to take the transpose when given a matrix.
  • t=Thread; lets me use t twice instead of Thread twice to save bytes.
  • Sort sorts a list (in increasing order).
  • Sort\@ maps the Sort function to each element of a list individually; when applied to a matrix, it sorts the rows.
  • t@# applies the transpose function to the input # of the main function.
  • - takes the negative of all of the entries so that sorting the rows of the transposed matrix (the columns of the original) sorts them in the desired way.
  • The outer -t[...] undoes the negative and the transpose, so all we really did was sort the columns largest-to-smallest.
  • ==# tests to see if this new column-sorted matrix is equal to the original input.
  • & ends the anonymous function with input # we defined.

You can try it online in the Wolfram Cloud sandbox by pasting code like the following and clicking Gear->"Evaluate cell" or hitting Shift+Enter or the numpad Enter:

t=Thread;-t[Sort/@-t@#]==#&@{{16,128,64,32},{8,32,0,8},{4,16,8,2},{4,0,0,0}}

Or for all test cases:

t=Thread;-t[Sort/@-t@#]==#&//Map[#,{{{16,0,64,8},{8,0,32,8},{4,0,32,2},{2,0,0,0}},{{16,128,64,32},{8,128,32,8},{4,16,8,2},{4,0,0,0}},{{16,0,64,8},{8,0,32,16},{32,0,128,2},{2,0,0,0}},{{16,128,64,32},{8,32,0,8},{4,16,8,2},{4,0,0,0}}}]&
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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