# Is it a good 2048 board?

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:

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!

• Comments are not for extended discussion; this conversation has been moved to chat. – Martin Ender Sep 3 '17 at 13:14

all$scanr1 max>>=(==) Try it online! Takes a list of columns, with empty spaces as 0. • Gives the wrong output for [[16,8,4,0],[16,0,4,4],[16,4,4,4],[16,4,4,4]]. – Jonathan Allan Aug 1 '17 at 13:39 • @JonathanAllan It returns false as it should, your 2nd column is [16,0,4,4] which is not monotonic. Or am I missing something? – I want to make games Aug 1 '17 at 14:07 • 0 is your placeholder for an empty cell, not a value of 0. – Jonathan Allan Aug 1 '17 at 14:09 • @Iwanttomakegames that comment was meant for you (replace "your" with "the"). – Jonathan Allan Aug 1 '17 at 15:12 • @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'. – dv02 Aug 1 '17 at 16:52 # 05AB1E, 4 bytes €{íQ Try it online! Same as my other two answers. I promise this is my last one until others have answered :) # 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? • 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.) – Zacharý Aug 2 '17 at 23:45 # 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 # Jelly, 4 bytes Ṣ€U⁼ Try it online! Input as an array of columns. Works with arbitrary-sized grids. • 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. – Jonathan Allan Aug 1 '17 at 12:16 • @JonathanAllan According to the specs, I think this is valid too – hyper-neutrino Aug 1 '17 at 14:22 • Yet that will now fail my suggested test case returning 0 rather than 1. – Jonathan Allan Aug 1 '17 at 14:35 • @JonathanAllan How do you filter in Jelly ._. I'd expect this to work but ḟ0 doesn't work – hyper-neutrino Aug 1 '17 at 15:05 • @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 – hyper-neutrino Aug 1 '17 at 17:35 # Python 3, 42 bytes lambda l:all(x==sorted(x)[::-1]for x in l) Try it online! Same algorithm as my Jelly answer # 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. • Why do you turn the result into a string? (''+) – Zacharý Aug 1 '17 at 17:37 • @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. – tsh Aug 2 '17 at 1:34 # 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. # 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 • after some boolean transform: v=>!v.some((x,i)=>i%4&&x>v[i-1]) – tsh Aug 3 '17 at 7:04 # 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.

# 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?)
• 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. – Cinaski Aug 2 '17 at 13:57
• @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. – Business Cat Aug 2 '17 at 14:01
• I'll just change it to one of the others I guess – Business Cat Aug 2 '17 at 14:02
• Never mind, I was not aware of that new rule. – Cinaski Aug 2 '17 at 14:07

# 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.

f[x]=1>0

Try it online!

# Dyalog APL, 2119 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.

# Clojure, 30 bytes

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

try it online

• Welcome to PPCG, and nice first post! – Zacharý Aug 6 '17 at 15:33

# 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
• Nice arrangement to skip the second U. You could do nn at the end as well ;) – ETHproductions Aug 1 '17 at 13:32
• 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. – Shaggy Aug 1 '17 at 13:34

# 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>.

# MY, 6662 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)

# Mathematica, 27 bytes

## Explanation:

• Thread is a weird general transpose-like operation that happens to take the transpose when given a matrix.
• 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: