Localizador de número de habitación

24

Localizador de número de habitación

Me encontré con una técnica interesante para resolver problemas en mi trabajo cuando un colega me dio el número de sala equivocado para una reunión. De vez en cuando, mientras se dirige a una reunión, un miembro de mi equipo me enviará el número de habitación equivocado, generalmente porque están apurados en su escritorio y presionan la tecla equivocada.

Curiosamente, al llegar a la habitación equivocada, normalmente puedo adivinar a qué habitación se referían realmente imaginando un teclado numérico :

y al adivinar un número adyacente pretendían presionar.

Reto

Su desafío es escribir una función que tome un número de oficina del edificio (000-999) y genere las posibles soluciones de error tipográfico, suponiendo que su colega solo escriba mal un dígito.

La siguiente tabla muestra qué números son adyacentes entre sí en un teclado numérico:

0 -> 1,2
1 -> 0,2,4
2 -> 0,1,3,5
3 -> 2,6
4 -> 1,5,7
5 -> 2,4,6,8
6 -> 3,5,9
7 -> 4,8
8 -> 5,7,9
9 -> 6,8

Entrada

Un número de 3 dígitos: 000-999. Suponga la entrada de exactamente 3 dígitos. Si el número es menor que 100 o menor que 10, se le darán los ceros iniciales. (es decir, 004 y 028).

Salida

Una lista de posibles habitaciones. Esto puede ser de la forma que desee, siempre que haya un delimitador entre los números de habitación. (es decir, espacio, coma, nueva línea, etc.) Si el número es menor que 100 o menor que 10, puede o no tener los ceros iniciales como salida, eso depende de usted. (es decir, 004 puede ser 004 04 4, y 028 puede ser 028 28)

Casos de prueba (los ceros iniciales son opcionales):

008 -> 108, 208, 018, 028, 005, 007, 009 
123 -> 023, 223, 423, 103, 113, 133, 153, 122, 126
585 -> 285, 485, 685, 885, 555, 575, 595, 582, 584, 586, 588
777 -> 477, 877, 747, 787, 774, 778
963 -> 663, 863, 933, 953, 993, 962, 966
555 -> 255, 455, 655, 855, 525, 545, 565, 585, 552, 554, 556, 558

Este es el , por lo que gana el código más corto en bytes para cada idioma.

Desarrollador en desarrollo
fuente
1
¿Podemos tomar la entrada como una lista de tres dígitos (0-9)?
HyperNeutrino
99
... y es por eso que las salas de reuniones deben tener nombres.
Jonathan Allan el
2
@JonathanAllan Es mucho más difícil para las personas nuevas encontrar "Sala de delfines" que "Sala 218" (suponiendo que los números de sala estén asignados en orden). Un compromiso sería ordenar alfabéticamente los nombres, pero entonces solo tienes 26.
Andrew dice que reinstala a Mónica el
1
@KellyLowder debería haber sido 933así que lo arreglé.
Jonathan Allan el
44
Relacionado, una vez trabajé en TI donde había un profesor que tuvo problemas con la tecnología de la sala varias semanas seguidas. Estaba en Bradley 210 (que yo sabía, Bradley era el nombre del edificio. El edificio de al lado, Matheson, estaba conectado a través de un puente del cielo en el tercer piso. Bradley tenía 5 pisos de altura, Matheson 4). Nunca podría decirme en qué habitación estaba correctamente. Una vez me dijo que estaba en "Matheson 605", que evidentemente no existía, y que no tenía ninguno de los dígitos correctos.
Draco18s

Respuestas:

13

Wolfram Idioma (Mathematica) , 112 106 bytes

Reconociendo que un teclado numérico es básicamente un 3x3 GridGraphcon bordes agregados para 0, obtenemos los dígitos adyacentes para cada dígito de entrada AdjacencyList.

Esto se puede ver a continuación:

EdgeAdd[GridGraph[{3,3},VertexLabels->"Name",GraphLayout->"SpringEmbedding"],{0<->1,0<->2}] rendimientos:

ingrese la descripción de la imagen aquí

Luego uso Tuplespara descubrir todos los posibles errores y elegir aquellos con exactamente un error con Selecty EditDistance. Por cierto, esto funcionará para números de habitación más largos y también puede aumentar el EditDistanceparámetro para permitir más de un error. Podría ser capaz de jugar golf un poco más lejos pero quería mostrar mi enfoque.

h@u_:=Select[Tuples[AdjacencyList[EdgeAdd[GridGraph[{3,3}],{0<->1,0<->2}],#]~Join~{#}&/@u],#~EditDistance~u==1&]

Versión un poco más de golf codificada a 3 números de habitación de longitud (106 bytes). Esto generará una lista de rango 3 correspondiente a cada dígito:

Thread/@ReplacePart[#~Table~3,{i_,i_}:>(AdjacencyList[GridGraph@{3,3}~EdgeAdd~{0<->1,0<->2},#]&/@#)[[i]]]&

Pruébalo en línea!

Kelly Lowder
fuente
También se podría usar otras funciones de distancia como DamerauLevenshteinDistanceen lugar de EditDistanceque también incluiría los errores de transposición.
Kelly Lowder
9

Python 2 , 89 bytes

lambda r:[r[:i]+[c]+r[i+1:]for i,n in enumerate(r)for c in`ord(u'ÌЋ>তŧ0ɃD'[n])`]

Pruébalo en línea!

El 1 st y 5 th personajes no pueden ser indicados aquí (navegador dependiente), pero la cadena completa es equivalente a[21, 204, 1035, 62, 157, 2468, 359, 48, 579, 68]

Barra
fuente
3

R , 190 bytes

function(x){l=list(c(1,2),c(0,2,4),c(0,1,3,5),c(2,6),c(1,5,7),c(2,4,6,8),c(3,5,9),c(4,8),c(5,7,9),c(6,8))
a=do.call(expand.grid, mapply(c,l[x+1],x))
a[apply(a,1,function(y){sum(x==y)==2}),]}

Pruébalo en línea!


Mi segundo intento en CodeGolf! Bastante largo, 190 bytes, pero lo mejor que pude hacer con R. ¡Curioso por ver si otros tienen comentarios o pueden hacerlo mejor!

Florian
fuente
1
un montón de cosas pequeñas: tienes un espacio extra en la segunda línea; abusar de la precedencia de :over */+-puede reducir algunos bytes en la primera línea, deshacerse de ellos do.call, tratarlos acomo matrixy transponerlos ahorra alrededor de 39 bytes: ¡ Pruébelo en línea!
Giuseppe
Eres bueno en esto! Gracias por la respuesta.
Florian
2

JavaScript (Firefox 30-57), 115 109 bytes

f=([c,...a],p=``)=>c?[...(for(n of``+[12,240,1350,26,157,2468,359,48,579,68][c])p+n+a.join``),...f(a,p+c)]:[]

Editar: guardado 6 bytes gracias a @ edc65 (aunque las sugerencias 0ahora aparecen después de otras sugerencias). Versión ES6, 118 112 bytes:

f=([c,...a],p=``)=>c?[...[...``+[12,240,1350,26,157,2468,359,48,579,68][c]].map(n=>p+n+a.join``),...f(a,p+c)]:[]
<input oninput=o.textContent=f(this.value).join`\n`><pre id=o>

Neil
fuente
Veo esto [para (...)] en muchos campos de golf de código, pero no lo entiendo completamente, y parece que no puedo encontrarlo en ninguna documentación. ¿Podría explicarlo o publicar un enlace a una explicación?
Anton Ballmaier
guardar 6 bytes[...[12,240,1350,26,157,2468,359,48,579,78][c]+'']
edc65
1
@AntonBallmaier [for(...)]fue una de las varias propuestas de sintaxis de comprensión de matriz que nunca llegaron a ser ECMAscript. Le permitió recorrer un iterador y filtrar y / o mapear sucintamente los resultados. (Lo encontré particularmente útil al hacer doble iteración).
Neil
2

Java, 205 177 bytes

b->{for(int c=0;c<3;c++){char[]d=b.toCharArray();for(char e:"12,024,0135,26,157,2468,359,48,579,68".split(",")[new Byte(""+d[c])].toCharArray()){d[c]=e;System.out.println(d);}}}

Sé que es largo en comparación con las otras respuestas. Mi excusa: está en Java.
Oracle debería cambiar el nombre toCharArraya algo así getCrs.

Créditos

-28 personajes de Kevin Cruijssen

Reinis Mazeiks
fuente
1
Algunas cosas pequeñas para jugar al golf. (String b)->puede ser justo b->y puede eliminar el final ;. En cuanto a las cosas reales para jugar al golf: solo se usa auna vez, por lo que puede eliminar String[]a=...;y usar "12,024,0135,26,157,2468,359,48,579,68".split(",")[...]directamente. Además, Byte.parseBytepuede ser new Byte. En total: 177 bytes .
Kevin Cruijssen
1
@KevinCruijssen gracias, esos son algunos trucos que tendré que aprender :)
Reinis Mazeiks
1
Los consejos para jugar golf en Java y los consejos para jugar golf en <todos los idiomas> pueden ser interesantes de leer en caso de que aún no lo haya hecho. :)
Kevin Cruijssen
2

Ruby 97 bytes

->i{c=0;i.map{|j|[12,204,1035,26,157,2468,359,48,579,68][j].digits.map{|k|f=*i;f[c]=k;p f};c+=1}}

Pruébalo en línea!

Alternativamente, 94 caracteres pero 100 bytes

->i{c=0;i.map{|j|"\fÌЋ\u001A\u009Dতŧ0ɃD".unpack("U*")[j].digits.map{|k|f=*i;f[c]=k;p f};c+=1}}

Pruébalo en línea!

Asone Tuhid
fuente
2

C (gcc) , 136 o 114 bytes

ASCII versión 136 bytes

m[]={12,240,1350,26,157,2468,359,48,579,68},p,i,X=10;f(n){for(i=100;i;i/=X)for(p=m[n/i%X];p;p/=X)printf("%d ",n/(i*X)*(i*X)+p%X*i+n%i);}

Pruébalo en línea!

Unicode 114108 bytes (TiO parece contar de manera extraña para esto)

Gracias a @ceilingcat por esta versión.

p,i,X=10;f(n){for(i=1e3;i/=X;)for(p=L"\fðՆ\32\x9dতŧ0ɃD"[n/i%X];p;p/=X)printf("%d ",n/i/X*i*X+p%X*i+n%i);}

Pruébalo en línea!

gastropner
fuente
@ceilingcat Hm. TiO dice 108 bytes.
Gastropner
No creo que TIO cuente correctamente los bytes UTF-8 en C. Intente cambiar el idioma a bash u otra cosa y observe cómo cambia el conteo de bytes.
ceilingcat
@ceilingcat Sí, también era débil localmente. El archivo guardado es 114, lo suficientemente cierto.
Gastropner
111 bytes
ceilingcat
1

Perl 5 , 120 85 + 2 ( -F) = 87 bytes

map{@,=@F;$,[$i]=$_,say@,for(12,240,1350,26,157,2468,359,48,579,68)[$_]=~/./g;$i++}@F

Pruébalo en línea!

Ahorró 35 bytes al tomar prestada una idea de la respuesta rubí de @ AsoneTuhid.

Xcali
fuente
1

Python 2 , 103 bytes

gracias a @Lynn por -4 bytes.

lambda n:{n[:i]+r+n[i+1:]for i,v in enumerate(n)for r in`0x134cd9a07d1e58feab643f7db24102`[int(v)::10]}

Pruébalo en línea!

ovs
fuente
Ahorre 4 bytes con: in`0x134cd9a07d1e58feab643f7db24102`[int(v)::10](lo intentéint('…',36) pero es un byte más largo).
Lynn
1

Julia 0.6 , 93 bytes

~r=[(R=copy(r);R[j]=i;R)for i=0:9,j=1:3 if(big(1)<<(i+10r[j]))&0x502A044228550A21102B05406>0]

Pruébalo en línea!

  • Toma un vector de dígitos y devuelve una lista en el mismo formato.
  • 0x502A044228550A21102B05406es un valor UInt128en el que se establece el 1+10jbit th si f iestá al lado jdel teclado numérico.
  • big(1)es un BigInt. Se utiliza para evitar el desbordamiento y utiliza menos caracteres que Int128(1)o UInt128(1).
Lucas
fuente
1

SQL (SQLite), 533 bytes

with m as (select 0 as i, 1 as o union values (0,2),(1,0),(1,2),(1,4),(2,0),(2,1),(2,3),(2,5),(3,2),(3,6),(4,1),(4,5),(4,7),(5,2),(5,4),(5,6),(5,8),(6,3),(6,5),(6,9),(7,4),(7,8),(8,5),(8,7),(8,9),(9,6),(9,8))select o || substr('008', 2, 1) || substr('008', 3, 1)from m where substr('008', 1, 1) = cast(i as text)union select substr('008', 1, 1) || o || substr('008', 3, 1)from m where substr('008', 2, 1) = cast(i as text)union select substr('008', 1, 1) || substr('008', 2, 1) || o from m where substr('008', 3, 1) = cast(i as text)

Sin golf

with m as (
    select 0 as i, 1 as o
    union
    values
    /*(0,1),*/(0,2),
    (1,0),(1,2),(1,4),
    (2,0),(2,1),(2,3),(2,5),
    (3,2),(3,6),
    (4,1),(4,5),(4,7),
    (5,2),(5,4),(5,6),(5,8),
    (6,3),(6,5),(6,9),
    (7,4),(7,8),
    (8,5),(8,7),(8,9),
    (9,6),(9,8)
)
select o || substr(s, 2, 1) || substr(s, 3, 1)
from m, t
where substr(s, 1, 1) = cast(i as text)
union
select substr(s, 1, 1) || o || substr(s, 3, 1)
from m, t
where substr(s, 2, 1) = cast(i as text)
union
select substr(s, 1, 1) || substr(s, 2, 1) || o
from m, t
where substr(s, 3, 1) = cast(i as text)

Explicación

La entrada es una sola fila de texto en la tabla tcon columna s. Según tengo entendido, de acuerdo con esta meta respuesta, esta es una forma aceptable de entrada. La entrada se puede crear de la siguiente manera.

drop table if exists t;
create table t (s text);
insert into t values('555'); -- Your input here

Solución anotada

with m as ( -- Using this in the "with" allows us to only type is once
    select 0 as i, 1 as o -- The first pair is here and it names the columns
    union
    values
    /*(0,1),*/(0,2),
    (1,0),(1,2),(1,4),
    (2,0),(2,1),(2,3),(2,5),
    (3,2),(3,6),
    (4,1),(4,5),(4,7),
    (5,2),(5,4),(5,6),(5,8),
    (6,3),(6,5),(6,9),
    (7,4),(7,8),
    (8,5),(8,7),(8,9),
    (9,6),(9,8)
)
select o || substr(s, 2, 1) || substr(s, 3, 1) -- concat the first wrong char with two correct chars
from m, t
where substr(s, 1, 1) = cast(i as text) -- when the first char is in the i (input) column from above
union
select substr(s, 1, 1) || o || substr(s, 3, 1)
from m, t
where substr(s, 2, 1) = cast(i as text)
union
select substr(s, 1, 1) || substr(s, 2, 1) || o
from m, t
where substr(s, 3, 1) = cast(i as text)
Capitán Hombre
fuente
1

Kotlin , 117 bytes

mapIndexed{i,c->"12,024,0135,26,157,2468,359,48,579,68".split(",")[c-'0'].map{replaceRange(i,i+1,it+"")}}.flatMap{it}

Embellecido

mapIndexed { i, c ->
    "12,024,0135,26,157,2468,359,48,579,68"
        .split(",")[c - '0']
        .map { replaceRange(i, i + 1, it + "") }
}.flatMap { it }

Prueba

fun String.f(): List<String> =
mapIndexed{i,c->"12,024,0135,26,157,2468,359,48,579,68".split(",")[c-'0'].map{replaceRange(i,i+1,it+"")}}.flatMap{it}

data class Test(val input:Int, val answers: List<Int>)

val tests = listOf(
    Test(8, listOf(108, 208, 18, 28, 5, 7, 9)),
    Test(123, listOf(23, 223, 423, 103, 113, 133, 153, 122, 126)),
    Test(585, listOf(285, 485, 685, 885, 555, 575, 595, 582, 584, 586, 588)),
    Test(777, listOf(477, 877, 747, 787, 774, 778)),
    Test(963, listOf(663, 863, 933, 953, 993, 962, 966)),
    Test(555, listOf(255, 455, 655, 855, 525, 545, 565, 585, 552, 554, 556, 558))
)

fun main(args: Array<String>) {
    for (r in tests) {
        val input = r.input.toString().padStart(3, '0')
        val expected = r.answers.map { it.toString().padStart(3, '0') }.sorted()
        val actual = input.f().sorted()
        if (expected != actual) {
            throw AssertionError("$input -> $actual | $expected")
        }
    }
}

TIO

TryItOnline

jrtapsell
fuente
0

Jalea , 35 bytes

ḷþị“-ⱮⱮVḟ|żṣ~ẋ³ɱgẆ’ḃ⁽¦ḳ¤$ṛ¦DŒp$¥"JẎ

Pruébalo en línea!

-1 gracias a Jonathan Allan .

Explicación siendo actualizada ...

Erik el Outgolfer
fuente
3
Sinceramente, no tengo idea de cómo se analiza esto, y mucho menos cómo funciona. Una explicación sería muy apreciada.
caird coinheringaahing
@cairdcoinheringaahing lo siento, no hay tiempo ahora
Erik the Outgolfer
-1 byte: Wẋ3->ḷþ
Jonathan Allan
0

T-SQL , 322 bytes

WITH m AS(SELECT LEFT(value,1)i,RIGHT(value,1)o FROM STRING_SPLIT('01,02,10,12,14,20,21,23,25,32,36,41,45,47,52,54,56,58,63,65,69,74,78,85,87,89,96,98',','))SELECT o+RIGHT(s,2)FROM t,m WHERE i=LEFT(s,1)UNION SELECT LEFT(s,1)+o+RIGHT(s,1)FROM t,m WHERE i=SUBSTRING(s,2,1)UNION SELECT LEFT(s,2)+o FROM t,m WHERE i=RIGHT(s,1)

La entrada se toma de la columna sde una tabla de una sola fila llamada t:

DROP TABLE IF EXISTS t
CREATE TABLE t (s CHAR(3))
INSERT INTO t VALUES('008')

Sin golf:

WITH m AS (
    SELECT LEFT(value,1) i, RIGHT(value,1) o
    FROM STRING_SPLIT('01,02,10,12,14,20,21,23,25,32,36,41,45,47,52,54,56,58,63,65,69,74,78,85,87,89,96,98',',')
)
SELECT o+RIGHT(s,2) FROM t,m WHERE i=LEFT(s,1)
UNION
SELECT LEFT(s,1)+o+RIGHT(s,1) FROM t,m WHERE i=SUBSTRING(s,2,1)
UNION
SELECT LEFT(s,2)+o FROM t,m WHERE i=RIGHT(s,1)

SQLFiddle

Razvan Socol
fuente