Gere números compatíveis com o teclado

29

Os layouts de teclado de computador mais comuns têm as teclas de dígitos decimais

1234567890

correndo no topo, acima das teclas de letras.

Permita que a vizinhança de um dígito decimal seja o conjunto de dígitos de sua própria tecla de dígito e das teclas de dígito imediatamente à esquerda e à direita, se existirem.

Por exemplo, o bairro de 0 é {0, 9}e o bairro de 5 é {4, 5, 6}.

Agora, defina um número compatível com o teclado como um número inteiro positivo (na forma decimal sem zeros à esquerda) que pode ser digitado no layout acima, de modo que cada dígito consecutivo no número após o primeiro dígito esteja próximo ao dígito anterior.

  • Todos os números de um dígito (1-9) são trivialmente compatíveis com o teclado.

  • Um número como 22321 é compatível com o teclado, pois todos os dígitos (sem contar o primeiro) estão próximos do dígito antes.

  • Um número como 1245 não é compatível com teclado, porque 4 não está na faixa de 2 (nem vice-versa).

  • Um número como 109 não é compatível com teclado, porque 0 não se encontra na vizinhança de 1. As extremidades não se alternam.

Ao colocar os números compatíveis com o teclado, do menor para o maior, podemos criar uma sequência inteira .

Aqui estão os primeiros 200 termos da sequência de números compatíveis com o teclado:

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

Desafio

Escreva um programa ou função que use um número inteiro positivo N (via stdin / linha de comando / função arg) e imprima (para stdout) ou retorne o termo enésimo na sequência de números amigáveis ​​do teclado.

Por exemplo, se a entrada for 191, a saída deve ser 4544.

A saída pode opcionalmente ter uma única nova linha à direita.

O menor envio em bytes vence.

Passatempos de Calvin
fonte
7
Aleatório fato: OEIS tem uma sequência relacionada para numpads
SP3000
Obrigado, @ Sp3000. Eu rolei até aqui imaginando exatamente isso.
Luser droog 14/05

Respostas:

8

Pitão, 27 24 bytes

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

Demonstração.

Melhorias no original:

  • Usando metd, em vez de .r ... _UJ: 2 bytes a menos. 1 direto, 1 por não precisar usar J.

  • Usando se em `Tvez de JT10: 1 byte a menos.


Começamos com a representação de cadeia de um número: `T.

Em seguida, convertemos a string em uma lista de dígitos e giramos os dígitos para trás em um, (9876543210) com metsd. Então, pegamos as 2 subsequências do elemento com .: ... 2. Essas subsequências são filtradas /h-FY3. Essa expressão corresponde a ((a-b)+1)/3, que é zero se, e somente se, a diferença entre ae bfor no máximo 1. Portanto, a lista filtrada ficará vazia se e somente se o número for compatível com o teclado. Com !, o resultado é verdadeiro apenas se o número for compatível com o teclado.

f ... hGfiltra para cima de G+1até que o resultado seja verdadeiro, fornecendo o primeiro número amigável de teclado igual G+1ou superior.u ... Q0aplica essa função a seus próprios Qtempos de saída , começando em 0, onde Qestá a entrada. Isso fornece o Qnúmero amigável do teclado, conforme desejado.

isaacg
fonte
4

Python 3, 112 102 bytes

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

Acompanhamos a contagem de números amigáveis ​​ainda necessários para encontrar no último número marcado k.

5 e 5 bytes salvos graças a @isaacg e @ Sp3000.

randomra
fonte
Use uma expressão lamba em vez de um retorno def. Lambas permitem padrões.
Isaacg
@isaacg Obrigado, eu não sabia como me recuperar com lambda.
Random #
Ah, certo. Operações unárias vêm em primeiro lugar. Meu erro.
Mbomb007
Você pode soltar o [:-1]nozip
Sp3000
4

CJam, 29 28 bytes

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

Experimente on-line no intérprete CJam .

Dennis
fonte
Existe uma prova fácil de que o limite superior do N-ésimo número amigável é N ** 2
Optimizer
Ainda não encontrei um. A prova N ** 4é bem fácil, pois há pelo menos 2 ** kKFN abaixo 10 ** k < 16 ** k. Substituir _*por 4#não alteraria a contagem de bytes, mas tornaria o código terrivelmente ineficiente.
Dennis
Então, seu código não está incorreto para um número de entrada grande?
Optimizer
11
Espero que não. Mas vou mudar até que eu saiba. resmunga
Dennis
3

CJam, 34 31 bytes

3 bytes salvos por Dennis.

Tenho certeza de que a brecha para Pyth pode ser fechada de alguma forma, mas não tenho tempo agora para jogar ainda mais ...

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

Teste aqui.

Martin Ender
fonte
Você pode substituir )_++por :_para salvar 2 caracteres e -z1>por m2/para salvar outro.
Dennis
@ Dennis Oh, esses são bons, obrigado!
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
}

Teste : executar trecho no Firefox

edc65
fonte
Eu não sei muito JS, mas você não poderia fazer algo assim abs(p-d)>1em vez de p-d>1|p-d<-1?
Alex A.
@AlexA. As expressões em expandido e golfed são equivalentes. Math.abs(p-d)>1é maior quep-d>1|p-d<-1
edc65 14/05
Ah ok. Eu sabia que eles eram equivalentes, só não sabia que você precisava do Math.prefixo.
Alex A.
2

Haskell, 90 80 bytes

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

Esta é uma função sem nome. Para usá-lo, chame-o com um parâmetro, por exemplo: o ([x|x<-[0..],all((<2).abs)$zipWith(-)=<<tail$[mod(1+fromEnum c)10|c<-show x]]!!) 199que retorna 5432.

Como funciona:

[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 encontrou alguns bytes para salvar. Obrigado!

nimi
fonte
Em vez de x<-[1..]... !!n-1, você pode fazer x<-[0..]... !!n.
Lynn
E então é claro que f n=[...]!!npode ser f=([...]!!).
Lynn
Eu o reduzi para uma única função, eliminando a:f=([x|x<-[0..],all((<2).abs)$zipWith(-)=<<tail$[mod(1+fromEnum c)10|c<-show x]]!!)
Lynn
@Mauris: uau, obrigado! Sem anós podemos eliminar ftambém.
nimi 15/05
2

Dardo, 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;}

Com quebras de linha:

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;
}

Veja / execute-o no DartPad

lrn
fonte
1

Lote - 520 bytes

Estremecer.

@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%
desgrudar
fonte
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}"

Alguns casos de teste:

$ for i in 1 10 11 99 100 200; do ./kfn.sh $i; done
1     
11    
12    
889   
890   
5433  
$ 
Trauma Digital
fonte
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}

Código ungolfed e testes abaixo. Isso certamente poderia ser melhorado mais.

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>

NinjaBearMonkey
fonte
0

Cobra - 135

Não faz isso há algum tempo, mas aqui vai:

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
Furioso
fonte
0

Pitão, 19 bytes

e.f.AgL1.aM.+|RTjZT

Experimente aqui.

Nota: O uso de commit é mais recente que esse desafio; portanto, não deve ser considerado como um substituto da resposta de isaacg. Isso ainda está competindo, no entanto.

Erik, o Outgolfer
fonte