Is it a good 2048 board?

26

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!

dv02

Posted 2017-08-01T01:53:16.100

Reputation: 383

Comments are not for extended discussion; this conversation has been moved to chat.

– Martin Ender – 2017-09-03T13:14:44.483

Answers

16

Haskell, 21 bytes

all$scanr1 max>>=(==)

Try it online!

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

xnor

Posted 2017-08-01T01:53:16.100

Reputation: 115 687

Gives the wrong output for [[16,8,4,0],[16,0,4,4],[16,4,4,4],[16,4,4,4]]. – Jonathan Allan – 2017-08-01T13:39:57.553

@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 – 2017-08-01T14:07:34.083

0 is your placeholder for an empty cell, not a value of 0. – Jonathan Allan – 2017-08-01T14:09:48.163

2@Iwanttomakegames that comment was meant for you (replace "your" with "the"). – Jonathan Allan – 2017-08-01T15:12:18.617

@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 – 2017-08-01T16:52:50.863

10

05AB1E, 4 bytes

€{íQ

Try it online!

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

HyperNeutrino

Posted 2017-08-01T01:53:16.100

Reputation: 26 575

9

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?

Adám

Posted 2017-08-01T01:53:16.100

Reputation: 37 779

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ý – 2017-08-02T23:45:34.287

7

Jelly, 4 bytes

Ṣ€U⁼

Try it online!

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

HyperNeutrino

Posted 2017-08-01T01:53:16.100

Reputation: 26 575

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 – 2017-08-01T12:16:17.363

@JonathanAllan According to the specs, I think this is valid too

– HyperNeutrino – 2017-08-01T14:22:40.327

Yet that will now fail my suggested test case returning 0 rather than 1.

– Jonathan Allan – 2017-08-01T14:35:41.077

@JonathanAllan How do you filter in Jelly ._. I'd expect this to work but ḟ0 doesn't work

– HyperNeutrino – 2017-08-01T15:05:02.720

You'd need to filter each.

– Jonathan Allan – 2017-08-01T15:07:42.227

@JonathanAllan oh right ._. thanks – HyperNeutrino – 2017-08-01T15:08:49.167

Save two like this.

– Jonathan Allan – 2017-08-01T16:09:42.053

@JonathanAllan Sorry, stupid trackpad being weird. Thanks for the golf! – HyperNeutrino – 2017-08-01T16:18:01.533

Turns out OP is ruling that if you use 0 for "empty cell" it counts as a zero (shrug). – Jonathan Allan – 2017-08-01T16:54:06.657

@JonathanAllan Lol. So am I allowed to use (nospace) as empty cells? XD (i'll read spec once more) – HyperNeutrino – 2017-08-01T17:09:30.047

Oh well turns out I need to rollback all of my edits /shrug – HyperNeutrino – 2017-08-01T17:09:58.327

Yeah, with the clarification in place, you shouldn't filter out the 0's. – Zacharý – 2017-08-01T17:25:32.420

@Zacharý Yay \o/ much un-ungolfing done :D – HyperNeutrino – 2017-08-01T17:25:49.880

@Hyper-Neutrino, JonathanAllan, Zacharý I'm sorry guys, I should have thought about this before. My first question, I'll try to improve ;) – dv02 – 2017-08-01T17:34:44.030

1@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 – HyperNeutrino – 2017-08-01T17:35:30.660

@DirtyDev Yeah, no problem! It's a nice little challenge. – Jonathan Allan – 2017-08-01T21:35:38.840

6

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

JAD

Posted 2017-08-01T01:53:16.100

Reputation: 2 898

5

Python 3, 42 bytes

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

Try it online!

Same algorithm as my Jelly answer

HyperNeutrino

Posted 2017-08-01T01:53:16.100

Reputation: 26 575

-8 bytes in Python 3 or -14 bytes in Python 2. – notjagan – 2017-08-01T15:43:36.343

@notjagan thanks – HyperNeutrino – 2017-08-01T15:50:18.753

5

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.

tsh

Posted 2017-08-01T01:53:16.100

Reputation: 13 072

Why do you turn the result into a string? (''+) – Zacharý – 2017-08-01T17:37:35.883

@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 – 2017-08-02T01:34:37.090

4

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.

Kamil Drakari

Posted 2017-08-01T01:53:16.100

Reputation: 3 461

4

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

Grax32

Posted 2017-08-01T01:53:16.100

Reputation: 1 282

after some boolean transform: v=>!v.some((x,i)=>i%4&&x>v[i-1]) – tsh – 2017-08-03T07:04:12.043

3

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.

Bergi

Posted 2017-08-01T01:53:16.100

Reputation: 967

3

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?)

Business Cat

Posted 2017-08-01T01:53:16.100

Reputation: 8 927

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 – 2017-08-02T13:57:59.367

@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 – 2017-08-02T14:01:08.083

I'll just change it to one of the others I guess – Business Cat – 2017-08-02T14:02:50.673

Never mind, I was not aware of that new rule. – Cinaski – 2017-08-02T14:07:32.147

3

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.

calc84maniac

Posted 2017-08-01T01:53:16.100

Reputation: 165

2

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.

Post Rock Garf Hunter

Posted 2017-08-01T01:53:16.100

Reputation: 55 382

Darn, this beats Python by 1 byte ;P – HyperNeutrino – 2017-08-01T02:22:29.987

@HyperNeutrino Well the xnor's beats python by 21. :P – Post Rock Garf Hunter – 2017-08-01T03:17:13.080

You can also define f as f(a:b:c)=a>=b&&f(b:c) – Cristian Lupascu – 2017-08-01T11:03:42.360

2

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]))

darrylyeo

Posted 2017-08-01T01:53:16.100

Reputation: 6 214

Which value are you expecting for empty cells? – Arnauld – 2017-08-01T09:02:18.157

2

Swift 4, 84 77 bytes

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

Try it online!

Mr. Xcoder

Posted 2017-08-01T01:53:16.100

Reputation: 39 774

2

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

Cinaski

Posted 2017-08-01T01:53:16.100

Reputation: 1 588

Does not work for cases that should return truthy which have zeros between column elements like this for example.

– Jonathan Allan – 2017-08-01T12:29:57.743

You're right, I'm working on a solution. BTW I'm not the only one having problems with empty cells ;) – Cinaski – 2017-08-01T12:57:40.617

Yeah, I can see that. I suggested a test case for it too. Ping when fixed and you'll get an upvote from me :) – Jonathan Allan – 2017-08-01T13:02:03.813

@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. – dv02 – 2017-08-01T16:27:29.577

@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. – Jonathan Allan – 2017-08-01T16:55:58.067

Don't change this, due to the clarification to the rules, this is valid. – Zacharý – 2017-08-01T17:36:38.717

2

Japt, 7 bytes

Tried a few different methods for this one but, in the end, the shortest I could come up with ended up being a port of tsh's JS solution.

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

P+U¥®n§

Test it


Explanation

Implicit input of array U.

P+U

Prepend U with an empty string, converting the array to a string.

¥

Check for equality, which casts the right hand side to a string, too.

®

Map over U.

Sort (n) by <=.

Implicitly output boolean result.

Shaggy

Posted 2017-08-01T01:53:16.100

Reputation: 24 623

Nice arrangement to skip the second U. You could do nn at the end as well ;) – ETHproductions – 2017-08-01T13:32:56.500

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 – 2017-08-01T13:34:58.603

2

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.

Zacharý

Posted 2017-08-01T01:53:16.100

Reputation: 5 710

Outgolfed by 73%! – Adám – 2017-08-02T12:48:41.837

2

Clojure, 30 bytes

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

try it online

Kolja

Posted 2017-08-01T01:53:16.100

Reputation: 121

Welcome to PPCG, and nice first post! – Zacharý – 2017-08-06T15:33:33.747

1

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)

Zacharý

Posted 2017-08-01T01:53:16.100

Reputation: 5 710

1

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

Jakob

Posted 2017-08-01T01:53:16.100

Reputation: 2 428

0

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}}}]&

Mark S.

Posted 2017-08-01T01:53:16.100

Reputation: 251