Reparar los períodos faltantes de mi dirección IPv4

37

A veces, cuando escribo una dirección IPv4, obtengo todos los números correctos, pero olvido escribir uno o más puntos. Me gustaría tener un programa (o función) que tome mi dirección IPv4 rota y muestre todas las ubicaciones válidas posibles de los períodos faltantes.

Entrada

La entrada siempre será una cadena que es una transformación de una dirección IPv4 válida (ver detalles a continuación). Siempre se habrá transformado únicamente por la eliminación de uno o más caracteres de punto.

Su envío no necesita manejar entradas fuera de este formato.

Salida

Una colección o lista, en ningún orden o formato particular, de cadenas que representan todas las direcciones IPv4 válidas que se pueden crear a partir de la entrada mediante la inserción de caracteres de punto en la entrada.

  • La salida puede ser una lista nativa del idioma u otro tipo de colección ordenada o no ordenada.
  • Alternativamente, puede ser una secuencia de cadena de dirección IPv4 delimitada de alguna manera clara.
    • Si usa un delimitador de un solo carácter para delimitar su cadena, no se permiten puntos ni dígitos como ese delimitador de un solo carácter. Me doy cuenta de que, a diferencia de los números, los períodos como delimitadores no son ambiguos (ya que cada cuarto período necesariamente sería un delimitador), pero en aras de la legibilidad, lo estoy rechazando.

Formato de dirección IPv4

Si bien las direcciones IPv4 son realmente solo una secuencia de cuatro octetos binarios, este desafío utiliza un formato decimal con puntos restringido.

  • Una dirección IPv4 son cuatro valores decimales separados por tres puntos.
  • Cada uno de los cuatro valores está en el rango 0de 255, inclusive.
  • Los ceros iniciales no están permitidos en ningún valor numérico. (Independiente de un solo carácter 0se permite; cualquier otro número que empieza con un cero no es: 052, 00, etc.)

Casos de prueba

La entrada está en la primera línea, la salida en la segunda línea (aquí, estructurada como una lista separada por comas de cadenas entre comillas, separadas por comas, rodeadas por [ ], pero puede usar cualquier formato o estructura razonable, como se especificó anteriormente). Algunos ejemplos tienen notas en una tercera línea para resaltar la aplicación de una regla particular.

192.168.1234
["192.168.1.234", "192.168.12.34", "192.168.123.4"]

192.1681234
["192.16.81.234", "192.168.1.234", "192.168.12.34", "192.168.123.4"]
(Note: 192.1681.2.34 (etc.) is illegal because 1681 is greater than 255)

1921681.234
["19.216.81.234", "192.16.81.234", "192.168.1.234"]

1921681234
["19.216.81.234", "192.16.81.234", "192.168.1.234", "192.168.12.34", "192.168.123.4"]

192.168.1204
["192.168.1.204", "192.168.120.4"]
(Note: 192.168.12.04 is illegal because of leading zero)

192.168.123
["1.92.168.123", "19.2.168.123", "192.1.68.123", "192.16.8.123", "192.168.1.23", "192.168.12.3"]

192.168.256
["192.168.2.56", "192.168.25.6"]
(Note: Any combination that would leave 256 intact is illegal)

120345
["1.20.3.45", "1.20.34.5", "1.203.4.5", "12.0.3.45", "12.0.34.5", "120.3.4.5"]
(Note: 12.03.4.5 (etc.) is illegal due to leading zero.)

012345
["0.1.23.45", "0.1.234.5", "0.12.3.45", "0.12.34.5", "0.123.4.5"]
(Note: the first segment must be 0, because `01` or `012` would be illegal.)

000123
["0.0.0.123"]

(Hice estos ejemplos a mano, así que avíseme de cualquier error que pueda encontrar).

apsillers
fuente
orden de salida es importante?
@YOU No: " Una colección o lista, sin ningún orden o formato en particular ... "
apsillers
Los ceros iniciales no están permitidos : ¿eso también se aplica a la entrada?
Luis Mendo
3
Entonces ... "000125" solo debería devolver una solución correcta ... 0.0.0.125?
Keeta
2
@Keeta Eso es exactamente correcto. (Lo acabo de agregar como un caso de prueba.)
apsillers

Respuestas:

9

Pyth, 24 bytes

f&q4lJcT\.!-J`M256jL\../

Pruébalo en línea

Cómo funciona

                      ./Q   all partitions of input
                  jL\.      join each on .
f                           filter for results T such that:
      cT\.                    split T on .
     J                        assign to J
    l                         length
  q4                          equals 4
 &                            … and:
           -J`M256              J minus the list of representations of [0, …, 255]
          !                     is false (empty)

Pyth, 17 bytes, muy lento

@FjLL\.,^U256 4./

Advertencia. No corras. Requiere aproximadamente 553 GiB de RAM.

Cómo funciona

       ,             two-element list of:
        ^U256 4        all four-element lists of [0, …, 255]
               ./Q     all partitions of input
  jLL\.              join each element of both on .
@F                   fold intersection
Anders Kaseorg
fuente
¡Agradable! Solo para mi propio entendimiento, "todas las particiones de entrada" significan todas las formas posibles de segmentar la entrada, ¿verdad? ¿Entonces haces cada división posible y luego vuelves a unir las divisiones con puntos, para que termines con un montón de candidatos como 1.9.2.1.6.8.1.2y 19.2.1.6.8.1.2etc.? (Pero obviamente, todos los inválidos se filtran)
apsillers
@apsillers Correcto.
Anders Kaseorg
16

C (gcc / linux), 125 121 bytes

i;f(char*a){do{char*y=a,s[99],*x=inet_ntop(2,&i,s,99);for(;*x&&!(*x^*y&&*x^46);++x)y+=*x==*y;*x|*y||puts(s);}while(++i);}

Recorre todas las direcciones IPv4 posibles y realiza una comparación personalizada que omite puntos adicionales en la dirección IP generada (pero no en la dirección de comparación principal) para decidir si se imprime o no. Muy lento, pero debe terminar dentro de 1 hora en una PC razonable .

orlp
fuente
Puedes eliminar el i=0;.
betseg
@ReleasingHeliumNuclei Pensé que no podía (una función debe ser reutilizable), pero ahora me doy cuenta de que después de que la función ivuelva a ser 0 ...
orlp
6

Perl 5, 91 bytes

<>=~/^(([1-9]?|1\d|2[0-4])\d|25[0-5])\.?((?1))\.?((?1))\.?((?1))$(?{print"$1.$3.$4.$5 "})^/

El programa espera una sola línea de una sola entrada y genera una lista de candidatos delimitada por espacios.

Explicación

El programa explota la función de retroceso de regex para recorrer todas las posibilidades de formar una dirección IPv4 válida a partir de la cadena de entrada.

^(([1-9]?|1\d|2[0-4])\d|25[0-5])\.?((?1))\.?((?1))\.?((?1))$

La expresión regular IPv4 con opcional ., nada de nota aquí.

(?{print"$1.$3.$4.$5 "})

Una expresión de evaluación de código que imprime el contenido de los grupos de captura.

^

Hacer que el partido falle y forzar el retroceso.

Ejecución de ejemplo

$ echo "012345" | perl G89503.pl
0.12.34.5 0.12.3.45 0.1.23.45 0.1.234.5 0.123.4.5
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
fuente
5

JavaScript (ES6), 147 141 135 bytes

f=(s,n=0)=>(a=s.split`.`)[3]?a.every(s=>s==`0`|s[0]>0&s<256)?s+' ':'':[...s].map((_,i)=>i>n?f(s.slice(0,i)+`.`+s.slice(i),i):``).join``
<input placeholder=Input oninput=o.textContent=f(this.value)><div id=o style=font-family:monospace;width:1em>Output

Editar: guardado 6 bytes gracias a @apsillers. Ahorró otros 6 bytes copiando la prueba de validez de @ YOU.

Neil
fuente
¿Hay alguna diferencia entre [1-9] | 0 y [0-9] o \ d ??
@apsillers Ah, sí, una versión anterior de mi código podría generar un seguimiento .que arrojaría la prueba, pero creo que esta versión está bien.
Neil
@YOU Lo importante es que 0tiene un $. (También le falta un ^, así que gracias por llamar mi atención).
Neil
@apsillers Lamentablemente spliceno funciona así, modifica la matriz y devuelve los elementos eliminados.
Neil
4

Python 3, 232 bytes

import re,itertools as t,ipaddress as k
R=range
i=input()
for d in R(5):
 for p in t.combinations(R(len(i)),d):
  n=i;o=0
  for a in p:n=n[:a+o]+'.'+n[a+o:];o+=1
  try:k.ip_address(n);print(n*(not re.search(r'\D?0\d',n)))
  except:0

Bastante simple: colocamos puntos en todas partes e imprimimos si la dirección IP con los puntos colocados es válida. Verificamos la validez de las direcciones IP mediante (ab) utilizando ipaddress.ip_address, lo que genera una excepción si la entrada no es una dirección IP válida. El desafío define algunas reglas adicionales que ip_addressno manejan (es decir, que no puede haber ceros a la izquierda), por lo que también las verificamos con una expresión regular y luego imprimimos.

Emite cada solución en una nueva línea, mezclada con un número arbitrario de líneas en blanco.

Ejemplo de ejecución:

$ echo 012345 | python fixip.py
0.1.23.45
0.1.234.5
0.12.3.45
0.12.34.5
0.123.4.5





$ echo 000123 | python fixip.py
0.0.0.123








_

Aquí está mi solución anterior de Python 2 de 248 bytes. Los niveles de sangría segundo y tercero son \t(pestaña sin procesar) y \t (pestaña sin procesar más espacio) respectivamente. Esto juega muy mal con Markdown, por lo que las pestañas han sido reemplazadas por dos espacios.

import socket,re,itertools as t
R=range
i=input()
for d in R(5):
 for p in t.combinations(R(len(i)),d):
  n=i;o=0
  for a in p:n=n[:a+o]+'.'+n[a+o:];o+=1
  try:
   socket.inet_aton(n)
   if n.count('.')==3and not re.search(r'\D?0\d',n):print n
  except:0

Requiere la entrada rodeada de comillas (por ejemplo "123.456.789"). Emite cada dirección IP generada en una nueva línea.

¡Guardado 9 bytes gracias a @grawity!

Cobre
fuente
1
¿ ipaddress.ip_address()Sería más corto que el control manual de aton +?
Grawity
3

Brachylog , 110 bytes

:ef:{".",@N.|.}ac:3f:{@n:"."rz:cacb.}a.
,4yeN,?:N:6i.@nMl4,M:{:7&<256}a
~c[A:B]h:@N:Bc.
:ef:{,"0":"9"y:.m?}ac.

Pruébalo en línea!

Monja permeable
fuente
2

Python 3, 262 260 bytes

p,l,L,T=set(),-1,len,tuple
while l<L(p):l=L(p);p|={T(z[:i]+(y[:j],y[j:])+z[i+1:])for z in set(p)or[T(input().split("."))]for i,y in enumerate(z)for j in range(1,L(y))}
print(['.'.join(x)for x in p if L(x)==4and all(y=='0'or y[0]!='0'and int(y)<256for y in x)])

No se utilizan bibliotecas, pero tarde y más tiempo, es posible que me falten algunas técnicas de golf obvias.

Resultados de todos modos.

for x in 192.168.1234 192.1681234 1921681.234 1921681234 192.168.1204 192.168.123 192.168.256 120345 012345 000123; do
echo $x | python3 ipv4.py
done;

['192.168.123.4', '192.168.1.234', '192.168.12.34']
['192.16.81.234', '192.168.1.234', '192.168.123.4', '192.168.12.34']
['19.216.81.234', '192.168.1.234', '192.16.81.234']
['19.216.81.234', '192.168.123.4', '192.168.12.34', '192.16.81.234', '192.168.1.234']
['192.168.1.204', '192.168.120.4']
['192.16.8.123', '19.2.168.123', '1.92.168.123', '192.168.1.23', '192.168.12.3', '192.1.68.123']
['192.168.25.6', '192.168.2.56']
['1.20.3.45', '1.203.4.5', '12.0.34.5', '120.3.4.5', '1.20.34.5', '12.0.3.45']
['0.1.23.45', '0.12.3.45', '0.12.34.5', '0.123.4.5', '0.1.234.5']
['0.0.0.123']

fuente
1
Pensé en copiar tu prueba de validez y me preguntaba si necesitas los paréntesis alrededor de la orcláusula.
Neil
@Neil, gracias, no los necesitaba.
USTED