Generar números amigables con el teclado numérico

22

Inspirado por Generate Keyboard Friendly Numbers .

Fondo

Muchos botones numéricos tienen el siguiente diseño:

789

456

123

    0    

Definimos la vecindad de un número como el conjunto de celdas ortogonalmente adyacentes a él en el teclado numérico que se muestra, incluido él mismo. Por ejemplo, el vecindario de 2 es {1,5,3,0,2}y el vecindario de 0 es {1,2,0}. Hay una lista del vecindario de cada número a continuación, arriba de los casos de prueba.

Definimos un número amigable para el teclado numérico como un entero positivo donde, cuando se escribe en decimal sin ceros a la izquierda, cada dígito, excepto el primero, está cerca del dígito anterior.

Por ejemplo,

  • 7856 es un número compatible con el teclado numérico porque 8 está cerca de 7, 5 está cerca de 8 y 6 está cerca de 5.
  • 1201 es un número compatible con el teclado numérico porque 2 está cerca del 1, 0 está cerca del 2 y 1 está cerca del 0.
  • 82 no es un número compatible con el teclado numérico porque 2 no está cerca del 8.
  • 802 no es un número compatible con el teclado numérico porque 0 no está cerca del 8 (los vecindarios no se ajustan).

Secuencia OEIS relacionada . Tenga en cuenta que esta secuencia relacionada es distinta porque cuenta 0como adyacente a en 7lugar de 1y 2.

Reto

Dado un número entero positivo n, devuelva los números amigables número n-1 o primer nteclado numérico, donde el primero es 1. Puede usar indexación basada en 0, donde el número amigable número-0 sería 1.

Barrios

El vecindario de cada dígito se enumera aquí:

0:{0,1,2}
1:{0,1,2,4}
2:{0,1,2,3,5}
3:{2,3,6}
4:{1,4,5,7}
5:{2,4,5,6,8}
6:{3,5,6,9}
7:{4,7,8}
8:{5,7,8,9}
9:{6,8,9}

Casos de prueba / secuencia

Estos son los primeros 100 términos

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 20, 21, 22, 23, 25, 32, 33, 36, 41, 44, 45, 47, 52, 54, 55, 56, 58, 63, 65, 66, 69, 74, 77, 78, 85, 87, 88, 89, 96, 98, 99, 100, 101, 102, 110, 111, 112, 114, 120, 121, 122, 123, 125, 141, 144, 145, 147, 200, 201, 202, 210, 211, 212, 214, 220, 221, 222, 223, 225, 232, 233, 236, 252, 254, 255, 256, 258, 320, 321, 322, 323, 325, 332, 333, 336, 363, 365, 366, 369, 410, 411, 412, 414, 441, 444, 445, 447]
fireflame241
fuente
55
Me gusta cómo este desafío solo considera enteros positivos (que mantienen la esencia y permiten que participen más idiomas) y permite mostrar la n -ésima o la primera n salidas para flexibilidad
Luis Mendo
Leí completamente el desafío, aquí hay un guión de "es este término válido en la secuencia": ¡ Pruébelo en línea!
Urna mágica de pulpo

Respuestas:

9

JavaScript (ES6), 104 93 89 88 bytes

Devuelve el enésimo término de la secuencia, 1 indexado.

f=(i,k,n=k,N=n/5>>1)=>(N?8530025>>(n%10*6191^N%10*6191)%26&1:!i--)?N?f(i,k,N):k:f(i,-~k)

Manifestación

Arnauld
fuente
Lo mejor que puedo obtener es 151 k=(n,a=1)=>n?k(n-([...(x=a+[]).slice(0,-1)].reduce((a,c)=>a*!!~"012 0124 01235 236 1457 24568 3569 478 5789 689".split` `[c].indexOf(x[i++]),i=1)),a+1):a-1tal vez algo que ayude, mi prueba es probablemente demasiado larga
Conor O'Brien
Esta respuesta lleva el concepto de números mágicos a un nivel completamente nuevo ... Ni siquiera entiendo cómo los encontraste o_O
scottinet
2
@scottinet En gran medida, mi explicación para esta respuesta también se aplica a esta. La diferencia absoluta no funcionó muy bien en eso, así que intenté con XOR. Como nota al margen, encontré otra fórmula que funcionó en el 96% de los casos sin la necesidad de una máscara de búsqueda. Pero procesar el 4% restante por separado era demasiado costoso en JS. No lo intenté en Jelly , y ahora no recuerdo la fórmula de todos modos ... ¯ \ _ (ツ) _ / ¯
Arnauld
Gracias por las explicaciones Esto sigue siendo impresionante :-)
scottinet
4

Perl 5 , 123 + 1 (-p) = 124 bytes

while($_){$r=@d=++$\=~/./g;map$r&&=(120,1240,12350,236,1457,24568,3569,478,5789,689)[$d[$_-1]]=~/$d[$_]/,1..$#d;$r&&$_--}}{

Pruébalo en línea!

Xcali
fuente
3

Jalea , 27 24 bytes

Devuelve los N primeros términos de la secuencia.

D⁽ÞȦ×^2\%26“⁷wð’æ»ḂẠ
1Ç#

Pruébalo en línea!

Este es un puerto de mi respuesta JS .

D⁽ÞȦ×^2\%26“⁷wð’æ»ḂẠ    - helper link: test numpad-friendliness of a number, e.g. 1257
D                       - get decimal digits             -> [1, 2, 5, 7]
    ×                   - multiply by ...
 ⁽ÞȦ                    - ... the integer 6191           -> [6191, 12382, 30955, 43337]
     ^2\                - bitwise XOR overlapping reduce -> [10353, 18613, 53666]
        %26             - modulo 26                      -> [5, 23, 2]
                æ»      - right-shift by each value ...
           “⁷wð’        - ... the integer 8530025        -> [266563, 1, 2132506]
                  Ḃ     - isolate the LSB                -> [1, 1, 0] which means that 1->2
                                                            and 2->5 are OK and 5->7 is not
                   Ạ    - all (0 if there's any 0)       -> 0, i.e. not numpad-friendly :'(

1Ç#                     - main link: return the [input] first matching numbers,
                          using our helper link as a monad and starting with 1
Arnauld
fuente
3

05AB1E , 24 23 bytes

µNSü‚εW_iO<ë<3BÆ}ÄR2‹}P

Pruébalo en línea!

Devuelve el enésimo número de la secuencia.

Explicaciones:

µNSü‚εW_iO<ë<3BÆ}ÄR2‹}P    Full program
µ                          Until counter is equal to input
 N                         Push current iteration number (e.g. 1025)
  S                        Split to a list of chars (-> ['1', '0', '2', '5'])
   ü‚                      Group into pairs (-> ['1', '0'], ['0', '2'], ['2', '5'])
     ε                     For each pair
      W_                      Is smallest digit equal to 0?
        iO<                      True: sum all digits and decrement 
           ë                     False: 
            <                       - decrement all digits
             3B                     - convert to base 3
               Æ                    - reduced substraction
                }             End if
                 Ä            Absolute value
                  R           Reverse 
                   2‹         1 if result is < 2, 0 otherwise
                     }     End for each
                      P    Cumulative product (1 if all pair results are 
                                     1, 0 otherwise)
                           -- implicit counter increment if stack value is 1

La idea principal es que, aparte de la 0 clave, cualquier dígito decrementado y convertido a base 3 tiene las siguientes propiedades:

  • los vecinos izquierdo y derecho tienen una diferencia absoluta de 1
  • los vecinos arriba y abajo tienen una diferencia absoluta de 10 que, invertida, es convenientemente igual a 1
  • cualquier otro par de teclas numéricas da como resultado valores diferentes, incluso cuando se invierte

Por supuesto, necesitamos una ifdeclaración para manejar la 0tecla del teclado numérico.

scottinet
fuente
Respuesta sólida, llegó a ofrecer más mejoras, no puedo encontrar ninguna. Oooo ... y ese par también te puso a la cabeza :).
Urna mágica del pulpo
No creo que hubiera podido llegar a esas 3 reglas, bastante impresionante; ¿Qué te dio la idea?
Urna mágica de pulpo
2

MATL , 29 27 bytes

`@J3:qEt!J*+hYAd|2>~A?@]NG-

Emite los primeros nnúmeros compatibles con el teclado numérico.

Pruébalo en línea!

Explicación

Cada dígito desde 1hasta9 se codifica como un número complejo que representa su posición en el teclado numérico, utilizando una cuadrícula de paso 2, donde la parte real representa la posición vertical y la parte imaginaria representa la posición horizontal. Así 1es 0+0j, 2es 0+2j, 3es 0+4j, 4es 2+0j, ..., 9es 4+4j.

El dígito 0se codifica como 0+1j, es decir, como si estuviera colocado exactamente entre 1y 2.

Para cada número del teclado numérico de usar candidato, se aplica una conversión de base "decimal" mediante los métodos anteriores números complejos en lugar de los dígitos 0, 1, ..., 9. Esto proporciona una matriz, de la cual se calculan las diferencias absolutas consecutivas. El número candidato es compatible con el teclado numérico si y solo si todas las diferencias absolutas son como máximo 2(es decir, el paso de la cuadrícula). Si ese es el caso, el número se deja en la pila.

El código usa un do... whilebucle, que sale cuando la cantidad de números en la pila es igual a la entrada n.

Una cuadrícula de unidades habría sido una opción más natural. Dígitos 1, 2y 0luego correspondería a 0+0j, 1+0jy 0.5+0jrespetuosamente. Pero es más golfista usar una cuadrícula de paso 2, porque multiplicar por 2(función E) y empujar 0+1j(función J) es un byte más corto que empujar 0+0.5j( J2/o.5j )

Luis Mendo
fuente
2

Jalea , 26 bytes

’d-,.⁸?3µ€ạ/S
Dṡ2Ç€<2Ạ
1Ç#

Pruébalo en línea!

-2 bytes gracias a caird coinheringaahing
-2 bytes gracias a Erik the Outgolfer

Explicación

’d-,.⁸?3µ€ạ/S  Helper Link; compute the distance between two keys z = [x, y]
      ?        Switch:
     ⁸         If z (is not 0):
’              Decrement
 d             Divmod by:
  -,.          Else: [-1, 0.5] (special position for 0)
       3       3; right argument for divmod otherwise ignored
        µ      Begin a new monadic link / end this link
         €     Compute the position for each [x, y]
           /   Reduce on
          ạ    Absolute Difference
            S  Sum (this gives the Manhattan Distance)
Dṡ2Ç€<2Ạ       Helper Link; determine if a number <z> is numpad friendly
D              Convert number to decimal digits
 ṡ             Slice into overlapping slices of length
  2            2 (pairs)
    €          For each pair,
   Ç           The distance between the keys
     <2        Compare with 2 (the distance between two adjacent keys is 1; corners 2; 0 - 1 and 0 - 2 are 1.5)
       Ạ       All; either all of the distances are less than 2 or there were no distances
1Ç#            Main Link; find the first (input) numpad friendly numbers
  #            nfind; counting up from _ collect the first _______ matches that are
1                                      1
                                                           (input)
 Ç             Numpad Friendly
Hiperneutrino
fuente
Puede eliminar el []de 2 bytes
caird coinheringaahing
@cairdcoinheringaahing gracias!
HyperNeutrino
1
Golf un par de descuento.
Erik the Outgolfer
2

Python 2 , 134 bytes

g=lambda n,k=1:n and g(n-(lambda l:all(abs(a-b)<1.2for a,b in zip(l,l[1:])))([~-d%3+~-d/3*1j-d/~d*1.5for d in map(int,`k`)]),k+1)or~-k

Pruébalo en línea!

Lynn
fuente
A medida que lo defina fy lo use una vez , podría incorporarlo y guardar dos bytes .
Jonathan Frech
1

Mathematica, 249 234 202 bytes

(a=o=1;While[a<=#,s=IntegerDigits@o;t=1;p=0;While[t+p<Length@s,If[!FreeQ[(IntegerDigits/@{210,4210,53210,632,7541,86542,9653,874,9875,986})[[s[[t]]+1]],s[[t+1]]],t++,p++]];If[t==Length@s,a++];o++];o-1)&


Pruébalo en línea!

gracias user202729 por comprimir datos (-32 bytes)

Mis resultados:

100 -> 447
1000 -> 20023
10000 -> 788777

J42161217
fuente
Creo que puede comprimir los datos usando IntegerDigits: IntegerDigits/@{210,4210,53210,632,7541,86542,9653,874,9875,986}y use FreeQ, Truse en Dolugar de For, use la notación infija para AppendToy use en Dolugar de Whilepara repetir Tr[1^s]tiempos, también elimine la variable p. Además, no ha demostrado que el algoritmo sea correcto, es decir, el número resultante siempre es menor que su índice al cuadrado, lo cual es necesario para que una respuesta sea válida.
user202729
1
@ user202729 Cambié muchas cosas. Mi respuesta es definitivamente válida. Comprimiré los datos ahora.
J42161217
¿Por qué el voto negativo?
J42161217
1

PHP, 124 + 1 bytes

while($argn-=$r)for($p=$r=~0,$x=++$n;$x>=1;$p=[7,23,47,76,178,372,616,400,928,832][$c],$x/=10)$r&=!!($p&1<<$c=$x%10);echo$n;

Ejecutar como tubería con -nRo probarlo en línea .

Tito
fuente
0

Java 8, 192 190 bytes

n->{int r=1,p;a:for(;n>0;){p=-1;for(int c:(r+++"").getBytes())if(p>-1&!"012;0124;01235;236;1457;24568;3568;478;5789;689".split(";")[c-=48].contains(p+""))continue a;else p=c;n--;}return~-r;}

Devuelve el (1 indexado) n en la secuencia.

Esto fue sorprendentemente más difícil de lo que pensé ... Probablemente solo teniendo algunos pedos cerebrales esta tarde ...

Explicación:

Pruébalo aquí

n->{                 // Method with integer as both parameter and return-type
  int r=1,           //  Return-integer
      p;             //  Previous digit
  a:for(;n>0;){      //  Loop (1) as long as the input is larger than 0
    p=-1;            //   Start `p` at an integer that is not 0-9 (-1 in this case)
    for(int c:(r+++"").getBytes())
                     //   Loop (2) over the digits of the current number
      if(p>=0        //    If this is not the first digit (`p` != -1),
         &!"012;0124;01235;236;1457;24568;3568;478;5789;689".split(";")[c-=48]
           .contains(p+""))
                     //    and the adjacent digits are NOT part of a NumberPad-Friendly Nr:
        continue a;  //     Go to the next iteration of loop (1)
      else           //    Else:
        p=c;         //     Set `p` to the current digit for the next iteration
                     //   End of loop (2) (implicit / single-line body)
      n--;           //   If we haven't encountered the `continue`, decrease `n` by 1
  }                  //  End of loop (1)
  return~-r;         //  Return the result-integer - 1
}                    // End of method
Kevin Cruijssen
fuente