生成键盘友好号码


29

最常见的计算机键盘布局具有十进制数字键

1234567890

沿着字母键上方的顶部运行。

设一个十进制数字的邻域为它自己的数字键和左,右数字键(如果存在)的一组数字。

例如,0的邻域是{0, 9},5的邻域是{4, 5, 6}

现在,将一个键盘友好数字定义为一个正整数(十进制形式,不带前导零),可以在上面的布局中键入该数字,以使第一个数字之后的数字中的每个连续数字都位于前一个数字的附近。

  • 所有一位数字(1-9)都很容易键盘操作。

  • 诸如22321这样的数字是键盘友好的,因为每个数字(不包括第一个数字)都在该数字的附近。

  • 诸如1245之类的数字键盘不友好,因为4不在2附近(反之亦然)。

  • 诸如109之类的数字适合键盘输入,因为0不在1附近。其末端不循环。

通过按最小到最大的顺序排列键盘友好数字,我们可以创建一个整数序列

这是键盘友好数字序列的前200个术语:

N KFN(N)
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 11
11 12
12 21
13 22
14 23
15 32
16 33
17 34
18 43
19 44
20 45
21 54
22 55
23 56
24 65
25 66
26 67
27 76
28 77
29 78
30 87
31 88
32 89
33 90
34 98
35 99
36 111
37 112
38 121
39 122
40 123
41 211
42 212
43 221
44 222
45 223
46 232
47 233
48 234
49 321
50 322
51 323
52 332
53 333
54 334
55 343
56 344
57 345
58 432
59 433
60 434
61 443
62 444
63 445
64 454
65 455
66 456
67 543
68 544
69 545
70 554
71 555
72 556
73 565
74 566
75 567
76 654
77 655
78 656
79 665
80 666
81 667
82 676
83 677
84 678
85 765
86 766
87 767
88 776
89 777
90 778
91 787
92 788
93 789
94 876
95 877
96 878
97 887
98 888
99 889
100 890
101 898
102 899
103 900
104 909
105 987
106 988
107 989
108 990
109 998
110 999
111 1111
112 1112
113 1121
114 1122
115 1123
116 1211
117 1212
118 1221
119 1222
120 1223
121 1232
122 1233
123 1234
124 2111
125 2112
126 2121
127 2122
128 2123
129 2211
130 2212
131 2221
132 2222
133 2223
134 2232
135 2233
136 2234
137 2321
138 2322
139 2323
140 2332
141 2333
142 2334
143 2343
144 2344
145 2345
146 3211
147 3212
148 3221
149 3222
150 3223
151 3232
152 3233
153 3234
154 3321
155 3322
156 3323
157 3332
158 3333
159 3334
160 3343
161 3344
162 3345
163 3432
164 3433
165 3434
166 3443
167 3444
168 3445
169 3454
170 3455
171 3456
172 4321
173 4322
174 4323
175 4332
176 4333
177 4334
178 4343
179 4344
180 4345
181 4432
182 4433
183 4434
184 4443
185 4444
186 4445
187 4454
188 4455
189 4456
190 4543
191 4544
192 4545
193 4554
194 4555
195 4556
196 4565
197 4566
198 4567
199 5432
200 5433

挑战

编写一个程序或函数,该程序或函数采用正整数N(通过stdin /命令行/函数arg)并打印(到stdout)或返回键盘友好数字序列中的第N个项。

例如,如果输入为191,则输出应为4544

输出可以有一个可选的尾随换行符。

以字节为单位的最短提交获胜。


7
随机事实:OEIS有一个相关的小键盘序列
Sp3000

谢谢@ Sp3000。我向下滚动到这里想知道那件事。
luser droog 2015年

Answers:


8

Pyth,27个 24个字节

uf!f/h-FY3.:metsd`T2hGQ0

示范。

对原始内容的改进:

  • 使用metd,而不是.r ... _UJ:少2个字节。1个直接,1个不必使用J。

  • 使用s`T代替JT10:少1个字节。


我们从数字的字符串表示形式开始`T

然后,我们将字符串转换为数字列表,并使用将数字向后旋转一位(9876543210)metsd。然后,我们用取2个元素子序列.: ... 2。这些子序列在上过滤/h-FY3。该表达式对应于((a-b)+1)/3,它是零,如果且仅当之间的差ab至多1。因此,当且仅当数目是键盘友好过滤列表是空的。使用!,仅当数字是键盘友好的时,结果才为true。

f ... hG从向上过滤,G+1直到结果为真为止,并给出等于G+1或大于第一个键盘友好编号。u ... Q0将此函数应用于自己的输出Q时间,从0开始,这里Q是输入。这将Q根据需要提供键盘友好号。


4

Python 3中,112个 102字节

f=lambda n,k=0:n+1and f(n-all(-2<~-int(a)%10-~-int(b)%10<2for a,b in zip(str(k),str(k)[1:])),k+1)or~-k

我们会跟踪仍需要查找的友好号码的数量n以及中最后检查的号码k

@isaacg和@ Sp3000节省了5和5个字节。


使用lamba表达式而不是def返回。兰巴允许默认值。
2015年

@isaacg谢谢,我不知道如何使用lambda递归。
randomra'5

对啊 一元运算优先。我的错。
mbomb007

您可以[:-1]zip
Sp3000

4

CJam,29 28字节

ri_4#{AbAfe|_1>.-W<3,:(-!},=

CJam解释器中在线尝试。


是否有简单的证据证明第N个友好数的上限为N ** 2
优化器

还没找到。的证明N ** 4很容易,因为2 ** k下面至少有KFN 10 ** k < 16 ** k。更换_*4#不会改变的字节数,但它会使代码效率极其低下。
丹尼斯

那么,对于一些较大的输入数字,您的代码是否正确?
Optimizer

1
希望不会。但我会更改它,直到我知道为止。抱怨
丹尼斯

3

CJam,34 31字节

Dennis保存了3个字节。

I'm sure the gap to Pyth can be closed somehow, but I don't have time right now to golf this further...

0q~{{)_s:_2ew{A,s(+f#~m2/},}g}*

Test it here.


You can replace )_++ with :_ to save 2 chars and -z1> with m2/ to save another.
Dennis

@Dennis Oh, those are nice, thank you!
Martin Ender

3

JavaScript (ES6), 95

F=k=>{for(i=0;k;k-=(f=1,p=NaN,[for(d of''+i)(d=(8-~d)%10,d-p>1|p-d>1?f=0:p=d)],f))++i;return i}

Ungolfed

F=k=>{
  for(i=0; k>0; )
  {
    ++i;
    f = 1; // presume i it's friendly
    p = NaN; // initial value so that first comparison gives false
    for(d of ''+i) // loop for each digit of i
    {
      // rotate digits 1->0, 2->1 ... 9->8, 0->9
      // note d is string, ~~ convert to number (golfed: 8-~d)
      d = (~~d+9) % 10 
      if (p-d>1 || p-d<-1) 
        f = 0 // not friendly
      else 
        // this can go in the 'else', if not friendly I don't care anymore
        p = d // move current digit to prev digit
    }
    k -= f // count if it's friendly, else skip
  }
  return i
}

Test : execute snippet in Firefox


I don't know much JS, but couldn't you do something like abs(p-d)>1 rather than p-d>1|p-d<-1?
Alex A.

@AlexA. The expressions in expanded and golfed are equivalent. Math.abs(p-d)>1 is longer than p-d>1|p-d<-1
edc65

Ah, okay. I knew they were equivalent, I just didn't know that you needed the Math. prefix.
Alex A.

2

Haskell, 90 80 bytes

([x|x<-[0..],all((<2).abs)$zipWith(-)=<<tail$[mod(1+fromEnum c)10|c<-show x]]!!) 

This is a function without a name. To use it, call it with a parameter, e.g.:([x|x<-[0..],all((<2).abs)$zipWith(-)=<<tail$[mod(1+fromEnum c)10|c<-show x]]!!) 199 which returns 5432.

How it works:

[x|x<-[0..]           ]  make a list of all integers x starting with 0
           ,             where
             c<-show x   each character in the string representation of x
  mod(1+fromEnum c)10    turned into the number '(ascii+1) mod 10'
 zipWith(-)=<<tail       then turned into a list of differences between neighbor elements
all((<2).abs)            only contains elements with an absolute value less than 2


                   !!    ... take the element given by the parameter (!! is 0 
                         based, that's why I'm starting the initial list with 0)

Edit: @Mauris found some bytes to save. Thanks!


Instead of x<-[1..] ... !!n-1, you can do x<-[0..] ... !!n.
Lynn

And then of course f n=[...]!!n can be f=([...]!!).
Lynn

I got it down to a single function, eliminating a: f=([x|x<-[0..],all((<2).abs)$zipWith(-)=<<tail$[mod(1+fromEnum c)10|c<-show x]]!!)
Lynn

@Mauris: wow, thank you! Without a we can eliminate f, too.
nimi

2

Dart, 92 bytes

f(n,[x=0]){t(x)=>x>9?((x+9)%10-((x~/=10)+9)%10).abs()>1||t(x):--n>0;while(t(++x));return x;}

With linebreaks:

f(n,[x=0]){
  t(x)=>x>9?((x+9)%10-((x~/=10)+9)%10).abs()>1||t(x):--n>0;
  while(t(++x));  
  return x;
}

See/run it on DartPad


1

Batch - 520 Bytes

Shudder.

@echo off&setLocal enableDelayedExpansion&set a=0&set b=0
:a
set/ab+=1&set l=0&set c=%b%
:b
if defined c set/Al+=1&set "c=%c:~1%"&goto b
set/am=l-2&set f=0&for /l %%a in (0,1,%m%)do (
set x=!b:~%%a,1!&set/an=%%a+1&for %%b in (!n!)do set y=!b:~%%b,1!
set z=0&set/ad=x-1&set/ae=x+1&if !e!==10 set e=0
if !d!==-1 set d=9
if !y!==!d! set z=1
if !y!==!e! set z=1
if !y!==!x! set z=1
if !y!==0 if !x!==1 set z=0
if !y!==1 if !x!==0 set z=0
if !z!==0 set f=1)
if !f!==0 set/aa+=1
if %a% NEQ %1 goto :a
echo %b%

1

Bash + coreutils, 120 bytes

seq $1$1|tr 1-90 0-9|sed 's#.#-&)%B)/3)||(((C+&#g;s/^/(0*((/;s/$/))*0)/'|bc|nl -nln|sed '/1$/d;s/   0//'|sed -n "$1{p;q}"

Some testcases:

$ for i in 1 10 11 99 100 200; do ./kfn.sh $i; done
1     
11    
12    
889   
890   
5433  
$ 

0

JavaScript ES6, 126 bytes

f=n=>{b=s=>[...++s+''].every((e,i,a,p=(+a[i-1]+9)%10)=>i?p==(e=+e?e-1:9)|p-e==1|e-p==1:1)?s:b(s)
for(p=0;n--;)p=b(p)
return p}

Ungolfed code and tests below. This could certainly be improved more.

f=function(n){
  b=function(s){
    return (s+'').split('').every(function(e,i,a){
      e=+e?e-1:9
      p=i?(+a[i-1]+9)%10:e
      return p==e|p-e==1|e-p==1
    })?s:b(s+1)
  }
  for(p=i=0;i<n;i++){
    p=b(p+1)
  }
  return p
}

var input = document.getElementById('n'), results = [];
input.onchange = function(){
  document.getElementById('s').innerHTML = f(input.value)
}
for(var i=0;i<200;i++){
  results.push(i + ':&nbsp;' + f(i))
}
document.getElementById('r').innerHTML=results.join('<br />')
N = <input type="number" id="n" min="1" value="191" /><br />
KBD(N) = <samp id="s">4544</samp>
<div id="r"></div>


0

Cobra - 135

Haven't done this in a while, but here goes:

def f(n,i=0)
    while n,if all for x in (s='[i+=1]').length-1get s[x+1]in' 1234567890'[(int.parse(s[x:x+1])+9)%10:][:3],n-=1
    print i

Ungolfed:

def fn(n as int)
    i = 0
    while n <> 0
        i += 1
        s = i.toString
        l = s.length - 1
        v = true
        for x in l
            k = (int.parse(s[x].toString) + 9) % 10
            if s[x + 1] not in ' 1234567890'[k : k + 3], v = false
        if v, n -= 1
    print i


0

Pyth, 19 bytes

e.f.AgL1.aM.+|RTjZT

Try it here.

Note: Uses commit newer than this challenge, so shouldn't be considered as an outgolf of isaacg's answer. This is still competing, though.

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.