解决火柴拼图


17

在令人困惑的SE上,存在所谓的“火柴问题”,其中数学是用火柴写的,并且允许您移动一定数量的火柴以获得某种属性。

在这个问题中,我们将只考虑以7段显示格式表示的整数。这是该格式的所有10位数字:

 __          __   __          __    __    __    __    __
|  |     |   __|  __|  |__|  |__   |__      |  |__|  |__|
|__|     |  |__   __|     |   __|  |__|     |  |__|   __|    

显示屏的每个部分都是一个“火柴棍”,可以独立于其余数字移动。火柴是不可分割和坚不可摧的,不能以任何方式将其破坏或移走。

一个常见的难题是采用以10为底的给定数字,并尝试在给定的移动次数中使最大数字成为可能。一次移动被认为是火柴棍从任何占用的插槽到任何其他未占用的插槽的移动。完全可以在数字的两边输入新数字,例如0可以变成77给出3个移动

 __      __  __      __   __      __   __
|  |    |  |        |  |    |       |    |
|__| ,   __|     ,     |      ,     |    |

但是,您不能将一个插槽分成2个,也不能在现有插槽之间创建新的插槽,例如,将4变成数字中间的11,或者在现有数字之间插入新的数字。每次移动都不需要输入正确的数字,但是最终结果应该是在以10为基数的七段显示中的正确数字。如果您不希望,则无需使用任何举动。与令人费解的问题不同,这是一个[tag:封闭式问题],您在答案中不得使用任何运算符(乘法,乘幂等)或数学常数(Pi,格雷厄姆数等)。

任务

编写一个程序或函数,该程序或函数将一个数字和一个移动数作为输入,并返回可以用原始数字上的多个移动数进行的最大数运算。

这是一个 问题,因此答案将以字节计分,字节越少越好。

测试用例

n, moves -> max
0, 1     -> 9
0, 3     -> 77
0, 4     -> 111
8, 3     -> 74
220, 1   -> 320
220, 2   -> 520
220, 3   -> 7227
220, 4   -> 22111
220, 5   -> 32111
747, 1   -> 747
747, 2   -> 7171
747, 3   -> 7711

有关


5
我...实际上是昨晚熬夜,琢磨着各种火柴

1
最后可以忽略中间形成的空插槽吗?例如919, 2 -> 991
DanTheMan


麦向导,正在使用哪个网格?
tuskiomi

@tuskiomi“但是,您不能将一个插槽分成2个插槽,也不能在现有插槽之间创建新插槽”
Post Rock Garf Hunter

Answers:


7

JavaScript的(ES6),297 286 279 267字节

以currying语法接受输入(s)(k),其中s是数字字符数组,而k是移动数(整数)。

s=>k=>(B=(n,b=0)=>n?B(n^n&-n,b+1):b,b=[...p='u"[k,iy#}m'].map(c=>c.charCodeAt()+2),r=[],g=(n,d='')=>n?n>0&&b.map((v,i)=>g(n-B(v),d+i)):r.push(d))(s.reduce((s,c)=>s+B(b[c]),M=0))&&b.map((_,j)=>r.map(n=>M=[...n+p].reduce((t,d,i)=>t+B(b[d]^b[s[i-j]]),0)>k*2|+n<M?M:n))|M

测试用例


怎么样?

形状数据和辅助功能

  • 数组b将数字的形状描述为7位整数,其中每一位都是一个段:

    7段

    例如,形状“ 7”是0b0100101 = 37。

  • 辅助函数B()以给定数字的二进制表示形式返回1的数字:

    B = (n, b = 0) => n ? B(n ^ n & -n, b + 1) : b

步骤1

我们首先计算输入数字中使用的火柴的数量:

s.reduce((s, c) => s + B(b[c]), 0)

第2步

我们将此值传递给递归函数g(),该函数使用可以精确地使用此数目的火柴棍构建的所有数字填充列表r

g = (n, d = '') =>
  n ?
    n > 0 &&
    b.map((v, i) => g(n - B(v), d + i))
  :
    r.push(d)

例如,g(5)将加载[ '17', '2', '3', '5', '71' ]r中

步骤三

现在,我们必须在允许的移动数k内选择r中的最高数字M,该数字实际上可以从输入数字中获得。

因为r中的每个数字n都使用与输入数字s一样多的火柴,所以将s转换为n所需的移动次数等于其每个数字之间的段差数目的一半

两个数字xy之间的分段差的数目由b [x] XOR b [y]的二进制表示形式中的1的数目给出。

最后,重要的是要注意,我们需要尝试几种可能的数字对齐方式,因为s的第一位未必映射到n的第一位。数字之间的移位由代码中的变量j给出。


1

Mathematica,188 197 200 203 170 174 个字节

注意:该代码仍然是错误的。我在做这个工作。

+ 30个字节的错误

(p=PadLeft;q=IntegerDigits;g=Join@@(#~q~2~p~7&/@ToCharacterCode["w$]m.k{% o"][[1+q@#]])&;h=(v=g@#2~#~96-g@i~#~96;Tr@v==0&&Tr@Abs@v<=2#3)&;For[i=10^Tr@g@#,!h[p,##]&&!h[PadRight,##],--i];i)&

%和之间的字符o应该是,0x7F但SE不允许。您可以单击pastebin链接来复制原始代码。

超过6-7根棍子时,代码会花费很多时间。(您可以将的起始值修改i为较小的数字以进行测试)

说明

g是一个辅助功能转换成数字表示棒(根据列表这里),如{1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1}220

h 是一个辅助函数,用于处理两个数字之间的左填充和右填充。

f10^Tr@g@#(上限)进行迭代,1以寻找一个整数,其小节表示的数量与原始数量相同,1 -> 0并且0 -> 1与原始数量相比,并且该数量小于或等于第二个参数。


我给了您+1,因为我从未见过胜出的答案得分比其他答案低。我认为这是因为缺少在线测试选项。也许有些拥有Mathematica的人可以来对其进行测试并验证其是否有效,因此您可以获得更多好评。或者,如果可能的话,有人可以将其转换为八度。
geokavel
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.