这个数字会成为一个很好的2048组合吗?


12

xkcd启发。

您的挑战是确定一个数字在2048游戏中是否会很好地组合在一起。您的输入将是一个数字,例如:

8224

输出将是该数字是否将构成一个很好的2048组合,对于此输入,它将是trueyes1或任何其他表示肯定结果的方式。

对于不熟悉游戏的人,这里有一个简单的解释:将两个的幂排列在一个网格上,如下所示:[2] [2]。磁贴可以向任意方向移动,如果两个相同的磁贴相遇,它们将成为两个的下一个幂(因此[2] [2],向左或向右移动时变为[4])。或者,您可以在这里尝试游戏

“好的2048组合”是什么意思?它表示任何数字,如果在游戏“ 2048”中可以将其组合为一个数字。(零表示空格,如果需要可以忽略。)请注意,数字可能是多个数字!但是,移动之间的数字一定不能改变。以下是一些示例/测试用例(“好”表示组合很好,“坏”表示不好):

  • 好:8224(8224-> 844-> 88-> 16)
  • 良好:2222(2222-> 44-> 8)
  • 良好:22048(22048-> 448-> 88-> 16)
  • 错误:20482(不能将外部2组合在一起,也不能将2048和2组合在一起)
  • 良好:20482048(20482048-> 4096)
  • 错误:210241024(210241024-> 22048,但这现在是[2] [2048],由于数字不能在两次移动之间改变,因此无法合并)
  • 好:2048(已经是一个数字)
  • 错误:2047年(不是2的幂)
  • 错误:11(游戏中没有1)
  • 好:000040000000(零是空白)

杂项规则:

  • 输入可以来自任何合理的地方,例如STDIN,函数参数,文件等。
  • 输出也可以在任何合理的地方,例如STDOUT,函数返回值,文件等。
  • 忽略网格大小- 22222222应该仍然输出true。
  • 只要是2的幂,最大数就没有最大值。因此,可能的数字是大于0的任意2的幂。
  • 对于那些担心零会引起歧义的人,情况并非如此。例如,22048可以解析为[2] [2048][2] [2] [0] [4] [8]。第一个无效,但是第二个有效,因此应输出true。
  • 这是,因此最短的代码(以字节为单位)将获胜!

2
我可以让服务器提供答案并仅从中上传输入下载答案吗?下载的总字节数为1
Bryan Chen

4
@Geobits 2048已经是一个数字或四个数字了。
约翰·德沃夏克

3
零不意味着有空格。1024是合法号码吗?空的空间应该是明确的……因此,我认为完全没有空间对这个问题没有帮助。
2014年

7
您的第三个示例显示22048应输出,good但事实并非如此。您不能2与合并,如果所有数字都应分开2048,则网格将是4x45个像元。所以也许您应该删除0?另外,您的第5个示例似乎无效,因为游戏在2048:) 停止
Teun Pronk 2014年

2
@undergroundmonorail我可以确认游戏中有4096个图块。
肯德尔·弗雷

Answers:


0

GolfScript,137个字符

[0`]1$,4*,{2\)?`}%+:W;[]\]][]\{{:A;W{A 1=\?!},{[.A~@,>\@~+\].~!{0-.,/@+\0}*;}%~}%.}do+.{~}%,{{.-1%}%.&{[{.2$={+)}*}*]{1|(}%}%}*{,1=},!!

输入必须在STD​​IN上给出。输出为0/ 1表示不好/很好的数字。大多数代码是解析可能的输入所必需的。

这个较短的版本(113个字符)执行了简单的移位测试,该测试对于的输入无法正常工作224422

[0`]1$,4*,{2\)?`}%+:W;[]\]][]\{{:A;W{A 1=\?!},{[.A~@,>\@~+\].~!{0-.,/@+\0}*;}%~}%.}do+{W{~[.:S]/[S.+]*}/,1=},!!

所有测试用例都可以在线检查。


3

Python:457 422个字符

z=range
def c(n):
 for x in z(1,12): 
  if int(n)==2**x:return 1
 return 0
def p(s):
 if s=='':return[]
 for i in z(len(s),0,-1):
  if c(s[:i])>0and p(s[i:])!=1:return [int(s[:i])]+p(s[i:])
 return 1
def r(a):
 if len(a)==1:return 1
 i,t=1,a[:1]
 while i<len(a):
  if a[i]==t[-1]:t[-1]*=2
  else:t+=[a[i]]
  i+=1
 if len(t)==len(a):return 0
 return r(t) 
def f(s):
 if p(s)==1or r(p(s))==0:print('bad')
 else:print('good')

函数f(s)得到一串数字,并相应地输出“好”或“坏”。我选择不使用0作为空格,因为空格在游戏中是没有意义的,并且在解析字符串时它们会产生歧义(22048是好是坏?)。它仅使用最大为2048的数字,但是可以在不添加字符的情况下进行更改。我还花了大约10个字符,就可以打印出所有组合数字的步骤。而且我意识到这段代码还不够完善。不用担心,即将进行编辑。


您可以使用空格和制表符来在缩进上保存一些字符。所以降价会打破它。
gcq 2014年

我认为它不适用于Python3.x。我可以做很多事情,但不确定是否可以与Haskell的答案竞争:)
2014年

是的,我忘记了这一点。
gcq 2014年

2

Haskell:285 254 253 237 230 227

用法-只需将其加载到ghci中,然后将字符串传递给h。

*Main> h "210241024"
False
*Main> h (replicate 1024 '2') -- very long string
True
*Main> h (replicate 1023 '2') -- odd one out
False

码:

t=i 0
i n=mod n 2<1&&(n<3||i(div n 2))
a%[]|i a=[[a]]|t=[];a%(b:c)=[a:d|d<-b%c,i a]++(a*10+b)%c
c(0:a)=c a;c(a:b:d)|a==b=(a+a):c d|t=a:c(b:d);c a=a
l a=c a/=a&&(g.c)a
g[a]=t;g a=l a||(l.reverse)a
h b=any g$0%(map(read.(:[]))b)

注释:i是检查数字是否为2的幂的乘方,将被语言打乱。%递归地生成所有2或0的幂的列表的解析cl递归测试图块是否可折叠左或良好。g测试图块是否可向左或向右折叠。h ((show (2^200))++(show (2^200)))磁贴上的编号没有限制-例如,对于标记为“ 160693804425899027554554092092341162602522202993782792835301376”的2个磁贴返回true。

编辑该漏洞的目的是不能正确折叠右侧的“ 88222288888”,但也发现了更多的高尔夫机会。


2

Perl,175-336字节

while(<>){chomp;$n="nothing";$\=("."x(1+/^[2048]+$/+/^((\d+)0*\2)+$/+((sprintf"%b",
$_)!~/1.*1/)))."\n";($o=$\)=~y/.\n/oh/;print$o;$m=length;for$i(1..$m){$a=$_;$r=
qr((\d*[2468])0*\2)0*/;($b=substr$a,0,$i,"")=~s/$r/$2+$2/ge;@n=$"="$b$a";push@n,$"while$"
=~s/$r/$2+$2/ge;($"%2&&next)||($">>=1)while$">1;$n="nice";(print)for@n;last}print$n}

保持基本要素不变:

$_=shift;$m=length;for$i(1..$m){$a=$_;$r=qr/((\d*[2468])0*\2)0*/;($b=substr$a,0,$i,"")=~
s/$r/$2*2/ge;$"="$b$a";1while$"=~s/$r/$2*2/ge;($"%2&&next)||($">>=1)while$">1;exit}die;

1个

哦.. 1.很好..

2

喔... 2 ...不错...

22

喔... 22 ... 4 ...不错...

42

哦..什么都没有..

422

哦.. 422 .. 44 .. 8.很好..

322

哦。没有。

336

哦。没有。

4224

哦..什么都没有..

4228

oo .. 4228 .. 448 .. 88 .. 16.尼斯..

16022481602248

ooh .. 1604481602248 .. 16088160448 .. 1601616088 .. 3216016 .. 3232 .. 64 .. nice ..

[ 64和256导致一些难以解决的歧义,贪婪的匹配无法解决...但是这些是不错的字节数。]

2048

喔... 2048 ...不错...


1

德尔福572 582个字符

编辑后的代码,限制设置为2 ^ 30,因此不会超过Delphi中的MaxInt值。

打高尔夫球

uses SysUtils,Classes;var t,j,c:integer;s,n:string;L:TStringList;function p(x:string):boolean;var r,i:int64;begin if x='0'then exit(1>0);i:=2;r:=StrToInt(x);while i<r do i:=i*2;p:=i=r;end;begin read(s);t:=0;L:=TStringList.Create;j:=1;while j<=Length(s)do begin for c:=9downto 1do begin n:=copy(s,j,c);if p(n)then break;end;if n>'0'then L.Add(n);j:=j+Length(n);end;for j:=0to L.Count-1do t:=t+StrToInt(L[j]);j:=0;repeat if j=L.Count-1then break;if L[j]=L[j+1]then begin L[j]:=IntToStr(StrToInt(L[j])*2);L.Delete(j+1);j:=0;end else inc(j);until L.Count=1;write(strtoint(L[0])=t);end.

不打高尔夫球

uses
  SysUtils,
  Classes;

var
  t,j,c:integer;
  s,n:string;
  L:TStringList;
  function p(x:string):boolean;
  var
    r,i:int64;
  begin
    if x='0'then exit(1>0);
    i:=2;r:=StrToInt(x);
    while i<r do
      i:=i*2;
    p:=i=r;
  end;
begin
    read(s);
    t:=0;L:=TStringList.Create;
    j:=1;
    while j<=Length(s)do
    begin
      for c:=9downto 1do
      begin
        n:=copy(s,j,c);
        if p(n)then break;
      end;
      if n>'0'then L.Add(n);
      j:=j+Length(n);
    end;
    for j:=0to L.Count-1do
      t:=t+StrToInt(L[j]);
    j:=0;
    repeat
      if j=L.Count-1then break;
      if L[j]=L[j+1]then
      begin
        L[j]:=IntToStr(StrToInt(L[j])*2);
        L.Delete(j+1);j:=0
      end
      else
        inc(j);
    until L.Count=1;
    write(strtoint(L[0])=t);
end.

编辑

所以我很好奇,想知道这些组合中有多少适合这个难题,并对其进行了测试。

对于其他同样好奇的人,也进行测试;)

但是好的,结果如下:
20736 combinations were tested and 1166 were great combinations

我必须说,有3个或更多零组合被跳过(即公理感?)
组合几乎是唯一的,这意味着组合2248822484224228都算作是一个伟大的组合。


1

Mathematica-218字节

f=MemberQ[DeleteCases[Map[FromDigits,l~Internal`PartitionRagged~#&/@Join@@Permutations/@IntegerPartitions@Length[l=IntegerDigits@#],{2}],{___,x_,___}/;!IntegerQ[2~Log~x]||x<2]//.{a___,x_,x_,b___}:>{a,2x,b},{_Integer}]&

非高尔夫版本:

f[n_] := MemberQ[
  DeleteCases[
      Map[
        FromDigits, 
        Internal`PartitionRagged[l, #] & /@ 
          Join @@ Permutations /@ IntegerPartitions[Length[l = IntegerDigits[n]]], 
        {2}
      ],
      {___, x_, ___} /; x < 2 || ! IntegerQ[2~Log~x]
    ]
  ] //. {a___, x_, x_, b___} :> {a, 2 x, b}, 
  {_Integer}
]

Internal\PartitionRagged`魔术取自这个问题

此解决方案可处理任意网格大小和任意大数。

这是一个195字节的工作方式类似于最多只有4瓦(所以实际的游戏版本f[22222222]False):

f=MemberQ[(d=DeleteCases)[d[ReplaceList[IntegerDigits@#,{a__,b___,c___,d___}:>FromDigits/@{{a},{b},{c},{d}}],0,2],{___,x_,___}/;!IntegerQ[2~Log~x]||x<2]//.{a___,x_,x_,b___}:>{a,2x,b},{_Integer}]&

我替换的地方

Map[
  FromDigits, 
  Internal`PartitionRagged[l, #] & /@ 
    Apply[
      Join, 
      Permutations /@ IntegerPartitions[Length[l = IntegerDigits@#]]
    ], 
  {2}
]

ReplaceList[
  IntegerDigits[n], 
  {a__, b___, c___, d___} :> FromDigits /@ {{a}, {b}, {c}, {d}}
]

只是想知道这是否与我的代码有相同的错误- DeleteCases看起来它删除了最左边的对,所以f[88222288888]会失败吗?
bazzargh 2014年

@bazzargh不,DeleteCases只需删除不是2的幂的零和数字。对的实际折叠是由rule完成的,该规则//. {a___, x_, x_, b___} :> {a, 2 x, b}适用于该数字及其相反方向。我实际上并不完全确定Mathematica将这些替换应用到的顺序,但是它可以工作。
Martin Ender 2014年

1

哈斯克尔-260263

import Data.Bits
p[x]=[[[x]]]
p(x:s)=do r@(h:t)<-p s;[[x]:r,(x:h):t]
q=filter(and.map(\n->(n::Integer)/=1&&n.&.(-n)==n)).map(filter(/=0)).map(map read).p
c(x:y:s)
 |x==y=2*x:c s
 |True=x:(c$y:s)
c x=x
r[x]=True
r l=c l/=l&&(r(c l)||r(c$reverse l))
f=or.map r.q

f是功能。例子:

> f"22228"
True
> f"20482044"
False

简要说明:
p返回所有拆分列表的方法。
q过滤那些仅包含2的幂(不包括1但包括0)的幂。
c尝试折叠字符串。
r反复进行左右折叠,直到只剩下1个元素,或者字符串不可折叠。


真好 不过存在一个错误c,请尝试输入“ 222244442222”-它返回true,但是在游戏中无法折叠。需要递归(2*x):c s
bazzargh 2014年

@bazzargh固定
mniip 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.