Risolvi i periodi mancanti del mio indirizzo IPv4


37

A volte quando scrivo un indirizzo IPv4, ottengo tutti i numeri giusti, ma dimentico di digitare uno o più punti. Mi piacerebbe avere un programma (o una funzione) che prenda il mio indirizzo IPv4 rotto e produca tutti i possibili posizionamenti validi dei periodi mancanti.

Ingresso

L'input sarà sempre una stringa che è una trasformazione di un indirizzo IPv4 valido (vedere i dettagli di seguito). Sarà sempre stato trasformato esclusivamente dall'eliminazione di uno o più caratteri punto.

L'invio non deve gestire input al di fuori di questo formato.

Produzione

Una raccolta o un elenco, in nessun ordine o formato particolare, di stringhe che rappresentano tutti gli indirizzi IPv4 validi che possono essere creati dall'input mediante l'inserimento di caratteri punto nell'input.

  • L'output può essere un elenco nativo della lingua o un altro tipo di raccolta ordinato o non ordinato.
  • In alternativa, può essere una sequenza di stringhe di indirizzi IPv4 delimitata in modo chiaro.
    • Se si utilizza un delimitatore a carattere singolo per delimitare la stringa, i punti e le cifre non sono consentiti come delimitatore a carattere singolo. Mi rendo conto che, diversamente dai numeri, i periodi come delimitatori non sono ambigui (dal momento che ogni quarto periodo sarebbe necessariamente un delimitatore) ma per motivi di leggibilità, lo sto vietando.

Formato indirizzo IPv4

Mentre gli indirizzi IPv4 sono in realtà solo una sequenza di quattro ottetti binari, questa sfida utilizza un formato decimale puntato limitato.

  • Un indirizzo IPv4 è un quattro valori decimali separati da tre punti.
  • Ognuno dei quattro valori sono nella gamma 0a 255, compreso.
  • Gli zeri iniziali non sono ammessi in nessun valore numerico. (Autonomo di un carattere 0che è consentito; qualsiasi altro numero che inizia con uno zero non è: 052, 00, etc.)

Casi test

L'input è sulla prima riga, l'output sulla seconda riga (qui, strutturato come un elenco separato da virgole di stringhe tra virgolette, separato da virgole, circondato da [ ], ma è possibile utilizzare qualsiasi formato o struttura ragionevole, come specificato sopra). Alcuni esempi hanno note su una terza riga per evidenziare l'applicazione di una particolare regola.

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"]

(Ho fatto questi esempi a mano, quindi per favore avvisami di eventuali errori che potresti trovare.)


l'ordine di uscita è importante?
TU

@YOU No: " Una raccolta o un elenco, in nessun ordine o formato particolare ... "
apsillers

Gli zeri iniziali non sono ammessi : vale anche per l'input?
Luis Mendo,

3
Quindi .... "000125" dovrebbe restituire solo una soluzione corretta ... 0.0.0.125?
Keeta,

2
@Keeta È esattamente corretto. (L'ho appena aggiunto come caso di test.)
apsillers

Risposte:


9

Pyth, 24 byte

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

Provalo online

Come funziona

                      ./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 byte, molto lento

@FjLL\.,^U256 4./

Avvertimento. Non correre. Richiede circa 553 GiB di RAM.

Come funziona

       ,             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

Bello! Solo per mia comprensione, "tutte le partizioni di input" significa tutti i modi possibili di segmentare l'input, giusto? Quindi fai ogni possibile spaccatura e poi ti ricongiungi con i periodi, così finisci con un sacco di candidati come 1.9.2.1.6.8.1.2e così 19.2.1.6.8.1.2via? (Ma ovviamente tutti quelli non validi vengono filtrati)
apsillers

@apsillers Correct.
Anders Kaseorg,

16

C (gcc / linux), 125 121 byte

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

Esegue il ciclo su tutti i possibili indirizzi IPv4 e esegue un confronto personalizzato che ignora i punti extra nell'indirizzo IP generato (ma non nell'indirizzo di confronto principale) per decidere se stampare o meno. Molto lento, ma dovrebbe finire entro 1 ora su un PC ragionevole .


È possibile rimuovere il i=0;.
betseg

@ReleasingHeliumNuclei Pensavo di non poterlo fare (una funzione deve essere riutilizzabile), ma ora mi rendo conto che dopo la funzione iè di nuovo 0 ...
orlp

6

Perl 5, 91 byte

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

Il programma prevede una sola riga di un singolo input e genera un elenco di candidati delimitati da spazi.

Spiegazione

Il programma sfrutta la funzionalità di backtracking di regex per eseguire il loop su tutte le possibilità di formare un indirizzo IPv4 valido dalla stringa di input.

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

Il regex IPv4 con facoltativo ., niente di importante qui.

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

Un'espressione di valutazione del codice che stampa il contenuto dei gruppi di acquisizione.

^

Fai fallire la partita e forza il backtracking.

Esempio di esecuzione

$ 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

5

JavaScript (ES6), 147 141 135 byte

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

Modifica: salvato 6 byte grazie a @apsillers. Salvati altri 6 byte copiando il test di validità di @ YOU.


c'è una differenza tra [1-9] | 0 e [0-9] o \ d ??
TU

@apsillers Ah sì, una versione precedente del mio codice potrebbe generare un trailing .che lancerebbe il test, ma penso che questa versione sia OK.
Neil,

@YOU Il punto importante è che 0ha un $. (Manca anche a ^, quindi grazie per avermi attirato la mia attenzione.)
Neil,

@apsillers Purtroppo splicenon funziona così, modifica l'array e restituisce tutti gli elementi rimossi.
Neil,

4

Python 3, 232 byte

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

Abbastanza semplice: posizioniamo i punti ovunque e stampiamo se l'indirizzo IP con i periodi inseriti è valido. Controlliamo la validità degli indirizzi IP utilizzando (ab) utilizzandoipaddress.ip_address , il che genera un'eccezione se l'input non è un indirizzo IP valido. La sfida definisce alcune regole aggiuntive che ip_addressnon gestiscono (vale a dire che non possono esserci zero iniziali), quindi controlliamo anche quelle con un'espressione regolare, quindi stampiamo.

Emette ciascuna soluzione su una nuova riga, mescolata con un numero arbitrario di righe vuote.

Esempio di esecuzione:

$ 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








_

Ecco la mia vecchia soluzione Python 2 da 248 byte. Il secondo e il terzo trattino sono rispettivamente \t(scheda non elaborata) e \t (scheda non elaborata più spazio). Questo gioca davvero male con Markdown, quindi le schede sono state sostituite da due spazi.

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

Richiede un input racchiuso tra virgolette (ad es "123.456.789" .). Emette ciascun indirizzo IP generato su una nuova riga.

Risparmiato 9 byte grazie a @grawity!


1
Sarebbe ipaddress.ip_address()più breve di aton + controllo manuale?
Grawity,


2

Python 3, 262 260 byte

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)])

Non sono state utilizzate biblioteche, ma tardi e più a lungo, forse mi mancano alcune ovvie tecniche di golf.

Risultati comunque.

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']

1
Ho pensato di copiare il test di validità e mi chiedevo se hai bisogno delle parentesi attorno alla orclausola?
Neil,

@Neil, grazie, non ne avevo bisogno.
TU
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.