Giornata mondiale IPv6 2014


22

Per celebrare l'anniversario della giornata mondiale IPv6 , Internet Society ha pubblicato una campagna per disattivare IPv4 il 6 giugno 2014 per One Day .


Gli indirizzi IPv6 possono essere rappresentati nella loro forma lunga come otto valori esadecimali a 16 bit separati da due punti. A seconda dell'indirizzo, possono anche essere abbreviati come descritto al punto 2 della sezione 2.2 Rappresentazione testuale degli indirizzi di RFC 3513 :

Per facilitare la scrittura di indirizzi contenenti zero bit è disponibile una sintassi speciale per comprimere gli zeri. L'uso di "::" indica uno o più gruppi di 16 bit di zeri. "::" può apparire solo una volta in un indirizzo. "::" può anche essere usato per comprimere zeri iniziali o finali in un indirizzo.

  • Le iscrizioni a questa sfida saranno programmi che accettano esattamente un indirizzo IPv6 formattato nel formato lungo o abbreviato e visualizzeranno lo stesso indirizzo in entrambi i formati lungo e corto, in quell'ordine.

  • L'input può provenire da argomenti della riga di comando, STDIN o qualsiasi altra sorgente di input adatta alla lingua scelta.

  • Le librerie o le utilità specifiche per l'analisi degli indirizzi IPv6 sono vietate (ad es. Inet_ {ntop, pton} () ).

  • Se l'indirizzo di input non è valido, l'output sarà vuoto (o viene fornito un messaggio di errore adatto che indica che l'indirizzo non è valido )

  • Nei casi in cui si ::verifica un accorciamento, può verificarsi solo un'operazione di accorciamento per un determinato indirizzo. Se esistono più di una potenziale operazione di accorciamento per un determinato indirizzo, deve essere utilizzata l'operazione che fornisce l'indirizzo più corto complessivo. Se esiste un pareggio a questo proposito, verrà utilizzata la prima operazione. Questo è illustrato negli esempi seguenti.

  • Scappatoie standard da evitare

Esempi:

Input                         Output

1080:0:0:0:8:800:200C:417A    1080:0:0:0:8:800:200C:417A
                              1080::8:800:200C:417A

FF01::101                     FF01:0:0:0:0:0:0:101
                              FF01::101

0:0:0:0:0:0:0:1               0:0:0:0:0:0:0:1
                              ::1

::                            0:0:0:0:0:0:0:0
                              ::

1:0:0:2:0:0:0:3               1:0:0:2:0:0:0:3
                              1:0:0:2::3

1:0:0:8:8:0:0:3               1:0:0:8:8:0:0:3
                              1::8:8:0:0:3

1:2:3:4:5:6:7:8               1:2:3:4:5:6:7:8
                              1:2:3:4:5:6:7:8

ABCD:1234                     <Invalid address format - no output>

ABCDE::1234                   <Invalid address format - no output>

1:2:3:4:5:6:7:8:9             <Invalid address format - no output>

:::1                          <Invalid address format - no output>

codegolf puzzle               <Invalid address format - no output>

Questo è , quindi la risposta più breve in byte del 6 giugno 2014 sarà accettata come vincente.


Di 'che l'ingresso è 1:0:0:2:2::3. L'output abbreviato sarebbe identico a quello o 1::2:2:0:0:3? Lo stesso per input non abbreviati in modo ottimale.
Martin Ender,

@ m.buettner In questo caso, ti lascerò scegliere.
Trauma digitale

È 1::2:0:0:0:3possibile un input?
user12205,


2
Penso che questo sia l'unico modo in cui qualcuno potrà mai farmi imparare l'ipv6. +1
Obversity,

Risposte:


4

JavaScript (ES6) - 198 , 183 , 180 , 188 , 187 byte

f=s=>/^(:[\da-f]{1,4}){8}$/i.test(':'+(s=s[r='replace'](d='::',':0'.repeat((n=8-s.split(/:+/).length%9)||1)+':')[r](/^:0|0:$/g,n?'0:0':0)))&&[s,s[r](/(\b0(:0)*)(?!.*\1:0)/,d)[r](/::+/,d)]

E, versione un po 'più lunga e interattiva con alcuni popup (203 byte):

/^(:[\da-f]{1,4}){8}$/i.test(':'+(s=(s=prompt())[r='replace'](d='::',':0'.repeat((n=8-s.split(/:+/).length%9)||1)+':')[r](/^:0|0:$/g,n?'0:0':0)))&&alert(s+'\n'+s[r](/(\b0(:0)*)(?!.*\1:0)/,d)[r](/::+/,d))

Ungolfed:

function ipv6(str) {
    "use strict";
    var zeros = 8 - str.split(/:+/).length % 9

        ,longIP = str
            .replace('::', ':0'.repeat(zeros || 1) + ':')
            .replace(/^:0|0:$/g, zeros ? '0:0' : '0')

        ,shortIP = longIP
            .replace(/(\b0(:0)*)(?!.*\1:0)/,':')
            .replace(/::+/,'::');

    return /^(:[\da-f]{1,4}){8}$/i.test(':'+longIP) && [longIP, shortIP];
}

Spiegazione:

Per calcolare la versione lunga dell'indirizzo IPv6:

8 - str.split(/:+/).length % 9- calcola quanti zeri dobbiamo inserire. Sono 8 - il numero dei valori esadecimali. Qui% 9 è una guardia, quindi non sarà mai un numero negativo.

replace('::', ':0'.repeat(zeros || 1) + ':')- Sostituisci "::" con zeri separati da due punti. Se non ci sono zeri da aggiungere, ne aggiunge ancora uno in modo che l'indirizzo non sia valido alla fine

replace(/^:0|0:$/g, zeros ? '0:0' : '0')- si tratta del caso speciale quando l'indirizzo inizia o termina con "::" poiché la splitfunzione aggiunge 1 al numero di valori esadecimali (:: 1 -> ["", "1"])

Questo è tutto! Ora calcoliamo la forma breve:

replace(/(\b0(:0)*)(?!.*\1:0)/,':') - Sostituisci la fila di zeri più lunga con due punti (non importa quanti).

replace(/::+/,'::') - rimuovere eventuali due punti in più

return /^(:[\da-f]{1,4}){8}$/i.test(':'+longIP) && [longIP, shortIP];- verifica se la versione lunga è valida IPv6 e restituisce entrambe le versioni o falsese il test ha esito negativo.

Test in Firefox:

>>> f('1080:0:0:0:8:800:200C:417A')
["1080:0:0:0:8:800:200C:417A", "1080::8:800:200C:417A"]
>>> f('FF01::101')
["FF01:0:0:0:0:0:0:101", "FF01::101"]
>>> f('0:0:0:0:0:0:0:1')
["0:0:0:0:0:0:0:1", "::1"]
>>> f('::')
["0:0:0:0:0:0:0:0", "::"]
>>> f('1:0:0:2:0:0:0:3')
["1:0:0:2:0:0:0:3", "1:0:0:2::3"]
>>> f('1:0:0:8:8:0:0:3')
["1:0:0:8:8:0:0:3", "1::8:8:0:0:3"]
>>> f('1:2:3:4:5:6:7:8')
["1:2:3:4:5:6:7:8", "1:2:3:4:5:6:7:8"]
>>> f('ABCD:1234')
false
>>> f('ABCDE::1234')
false
>>> f('1:2:3:4:5:6:7:8:9')
false
>>> f(':::1')
false
>>> f('1:2:3:4::a:b:c:d')
false
>>> f('codegolf puzzle')
false

Molto meglio del mio! Ho solo bisogno di una correzione per gestire input come questo :: 1 :,: 1 ::
edc65

Questo accettò l'invalido1:2:3:4::a:b:c:d
kernigh il

6

Javascript (E6) 246 305 284 292 319

Caso speciale fortemente rivisto per :: fase di compressione specificamente gestita, evita il ciclo for (ma non molto più breve) Sono sicuro che la fase di compressione finale può essere ridotta. Non adesso comunque

F=i=>(c=':',d=c+c,z=':0'.repeat(9-i.split(c,9).length)+c,i=i==d?0+z+0:i[R='replace'](/^::/,0+z)[R](/::$/,z+0)[R](d,z>c?z:d),/^(:[\da-f]{1,4}){8}:$/i.test(k=c+i+c)&&[i,k[R]((k.match(/:(0:)+/g)||[]).sort().pop(),d)[R](/^:([^:])|([^:]):$/g,'$1$2')])

Grazie a nderscore

Come programma

Input e output usando js popup, in sostanza: p=prompt,p(F(p())) riscrivendo con popup e senza la definizione della funzione, il conteggio dei caratteri dovrebbe essere inferiore a 260

Ungolf e commentato un po '

F = i => (
  c = ':',
  d = c+c,
  z = ':0'.repeat(9-i.split(c,9).length) + c, 
  i = i == d ? 0+z+0 /* special case '::' */
    : i.replace(/^::/,0+z) /* special case '::...' */
       .replace(/::$/,z+0) /* special case '...::' */
       .replace(d, z > c ? z : d), /* here, if z==c, not valid: too much colons */
  /^(:[\da-f]{1,4}){8}:$/i.test(k = c+i+c) /* Check if valid */
  && [
   i, 
   k.replace((k.match(/:(0:)+/g)||[]).sort().pop(),d) /* find longest 0: sequence and replace it */
    .replace(/^:([^:])|([^:]):$/g,'$1$2') /* cut leading and trailing colons */
  ]
)

Test in console

i=['1080:0:0:0:8:800:200C:417A'
, '::1:2:3:4:5:6:7', '1:2:3:4:5:6:7::'
, '1:2:3:4::5:6:7:8'
, ':1:2:3:4:5:6:7', '1:2:3:4:5:6:7:'
, 'FF01::101', '0:0:0:0:0:0:0:1'
, '::', '1::', '::1', ':::1', '1:::'
, '1:0:0:2:0:0:0:3', '1:0:0:0:2:0:0:3', '1::8:0:0:0:3'
, '1:2:3:4:5:6:7:8'
, 'ABCD:1234', 'ABCDE::1234', ':::', '::::::::::'
, '1:2:3:4:5:6:7:8:9', '::::1', 'codegolf puzzle'];
i.map(x=>x+' => '+F(x)).join('\n')

Uscita di prova

"1080:0:0:0:8:800:200C:417A => 1080:0:0:0:8:800:200C:417A,1080::8:800:200C:417A
::1:2:3:4:5:6:7 => 0:1:2:3:4:5:6:7,::1:2:3:4:5:6:7
1:2:3:4:5:6:7:: => 1:2:3:4:5:6:7:0,1:2:3:4:5:6:7::
1:2:3:4::5:6:7:8 => false
:1:2:3:4:5:6:7 => false
1:2:3:4:5:6:7: => false
FF01::101 => FF01:0:0:0:0:0:0:101,FF01::101
0:0:0:0:0:0:0:1 => 0:0:0:0:0:0:0:1,::1
:: => 0:0:0:0:0:0:0:0,::
1:: => 1:0:0:0:0:0:0:0,1::
::1 => 0:0:0:0:0:0:0:1,::1
:::1 => false
1::: => false
1:0:0:2:0:0:0:3 => 1:0:0:2:0:0:0:3,1:0:0:2::3
1:0:0:0:2:0:0:3 => 1:0:0:0:2:0:0:3,1::2:0:0:3
1::8:0:0:0:3 => 1:0:0:8:0:0:0:3,1:0:0:8::3
1:2:3:4:5:6:7:8 => 1:2:3:4:5:6:7:8,1:2:3:4:5:6:7:8
ABCD:1234 => false
ABCDE::1234 => false
::: => false
:::::::::: => false
1:2:3:4:5:6:7:8:9 => false
::::1 => false
codegolf puzzle => false"   

Preferirei un programma piuttosto che una funzione. Non conosco javascript abbastanza bene da sapere se questo è possibile.
Digital Trauma,

@nderscore Oops - errore di battitura. Corretto in un nuovo commento.
Trauma digitale,

Potrebbe essere trasformato in un programma prendendo input da prompt(). Ecco alcune ottimizzazioni che lo portano a 290: pastie.org/private/3ccpinzqrvvliu9nkccyg
nderscore,

@nderscore: grazie, la prima sostituzione non funziona per input = '::', comunque ottimo lavoro!
edc65,

@ edc65 Ho trovato una soluzione per sostituire :) pastie.org/private/kee0sdvjez0vfcmlvaxu8q
nderscore,

4

Perl - 204 176 190 191 197

(202 caratteri + 2 per -pbandiera)

$_=uc;(9-split/:/)||/^:|:$/||last;s/^::/0::/;s/::$/::0/;s|::|':0'x(9-split/:/).':'|e;/::|^:|:$|\w{5}|[^A-F0-:].*\n/||(8-split/:/)and last;s/\b0*(?!\b)//g;print;s/\b((0:)*0)\b(?!.*\1:0\b)/::/;s/::::?/::/

Esempio:

$ perl -p ipv6.pl <<< 1:0:2:0::3
1:0:2:0:0:0:0:3
1:0:2::3
$ perl -p ipv6.pl <<< somethinginvalid
$ perl -p ipv6.pl <<< 1:2:0:4:0:6::8
1:2:0:4:0:6:0:8
1:2::4:0:6:0:8

Spiegazione:

# -p reads a line from stdin and stores in $_
#
# Convert to uppercase
$_ = uc;

# Detect the annoying case @kernigh pointed out
(9 - split /:/) || /^:|:$/ || last;

# Fix :: hanging on the beginning or the end of the string
s/^::/0::/;
s/::$/::0/;

# Replace :: with the appropriate number of 0 groups
s|::|':0' x (9 - split /:/) . ':'|e;

# Silently exit if found an extra ::, a hanging :, a 5-char group, an invalid
# character, or there's not 8 groups
/::|^:|:$|\w{5}|[^A-F0-:].*\n/ || (8 - split /:/) and last;

# Remove leading zeros from groups
s/\b0*(?!\b)//g;

# Output the ungolfed form
print;

# Find the longest sequence of 0 groups (a sequence not followed by something
# and a longer sequence) and replace with ::
# This doesn't replace the colons around the sequence because those are optional
# thus we are left with 4 or 3 colons in a row
s/\b((0:)*0)\b(?!.*\1:0\b)/::/;

# Fix the colons after previous transformation
s/::::?/::/

# -p then prints the golfed form of the address

1
"Morto a ipv6.pl linea 1, <> linea 1" . Questo è stato chiesto nei commenti alla domanda. Se c'è un messaggio, deve essere chiaro che è a causa di un messaggio non valido. Ho cercato di chiarire questo nella domanda. Altrimenti sembra buono!
Trauma digitale,

1
@DigitalTrauma Modificato diein un'uscita silenziosa.
mniip,

1
Un insetto? Questo programma accetta l'indirizzo non valido 1:2:3:4::a:b:c:d. Si tratta di un caso speciale fastidioso, perché la maggior parte gli indirizzi di otto colon non sono validi, ma ::2:3:4:a:b:c:de 1:2:3:4:a:b:c::sono entrambe valide.
kernigh,

3

sed, 276

Ho 275 byte in ipshorten.sed, più 1 byte affinché lo -rswitch in sed -rfutilizzi espressioni regolari estese. Ho usato OpenBSD sed (1) .

Uso: echo ::2:3:4:a:b:c:d | sed -rf ipshorten.sed

s/^/:/
/^(:[0-9A-Fa-f]{0,4})*$/!d
s/:0*([^:])/:\1/g
s/://
s/::/:=/
s/(.:=)(.)/\10:\2/
s/^:=/0&/
s/=$/&0/
:E
/(.*:){7}/!{/=/!d
s//=0:/
bE
}
s/=//
/^:|::|:$|(.*:){8}/d
p
s/.*/:&:/
s/:((0:)+)/:<\1>/g
:C
s/0:>/>0:/g
/<0/{s/<>//g
bC
}
s/<>(0:)+/:/
s/<>//g
/^::/!s/://
/::$/!s/:$//

Uso 22 espressioni regolari, poiché sed non può confrontare numeri o creare array. Per ogni riga di input, sed esegue i comandi e stampa la riga. Durante il test, ho inserito diverse righe di presunti indirizzi IP in un file e ho inviato questo file a sed. Un riferimento alle espressioni regolari estese è in re_format (7) .

  1. s/^/:/aggiunge due punti in più all'inizio della riga. Uso questi due punti extra per giocare a golf i prossimi due comandi.
  2. /^(:[0-9A-Fa-f]{0,4})*$/!dcontrolla se l'intera riga corrisponde a zero o più gruppi di due punti seguiti da zero a quattro cifre esadecimali. annulla !il segno di spunta, quindi delimina le righe con numeri esadecimali troppo grandi o con caratteri non validi. Quando delimina una riga, sed non esegue più comandi su questa riga.
  3. s/:0*([^:])/:\1/gelimina 0 iniziali da ogni numero. Sarebbe cambiato :0000:0000:in :0:0:. Devo farlo perché il mio ciclo di contrazione funziona solo con 0 a una cifra.
  4. s/://cancella i due punti in più. Elimina solo i primi due punti.
  5. s/::/:=/cambia il primo ::in :=. È così che i comandi successivi possono corrispondere =anziché ::, e quindi =non contano come due punti. Se non c'è ::, questa sostituzione non fa nulla di sicuro.
    • Ora ::devi fare almeno uno 0, ma ci sono tre diversi casi per posizionare questo 0.
  6. s/(.:=)(.)/\10:\2/è il primo caso. Se ::era tra altri due personaggi, allora :=diventa :=0:. Questo è l'unico caso che aggiunge due punti.
  7. s/^:=/0&/è il secondo caso. Se ::era all'inizio della riga, inserisci 0 lì.
  8. s/=$/&0/è il terzo caso, per ::fine linea.
  9. :E è l'etichetta per il ciclo di espansione.
  10. /(.*:){7}/!{/=/!dinizia un blocco condizionale se la linea ha meno di 7 punti. /=/!delimina le linee che non avevano ::e non abbastanza punti.
  11. s//=0:/aggiunge un colon. Vuoto //ripete l'ultima espressione regolare, quindi questo è davvero s/=/=0:/.
  12. bEsi dirama verso :Eper continuare il ciclo.
  13. }chiude il blocco. Ora la linea ha almeno sette punti.
  14. s/=//cancella =.
  15. /^:|::|:$|(.*:){8}/dè un controllo finale dopo l'espansione. Elimina le linee con due punti iniziali, un extra ::che non è stato espanso, due punti finali o otto o più due punti.
  16. p stampa la linea, che è un indirizzo IP in formato lungo.
  17. s/.*/:&:/ avvolge l'indirizzo in due punti in più.
    • Il prossimo compito è trovare il gruppo più lungo di 0, come :0:0:0:, e contrarlo ::.
  18. s/:((0:)+)/:<\1>/gmangia ogni gruppo di 0, quindi :0:0:0:diventerebbe :<0:0:0:>.
  19. :C è l'etichetta per il ciclo di contrazione.
  20. s/0:>/>0:/gsposta uno 0 da ogni bocca, così :<0:0:0:>diventerebbe :<0:0:>0:.
  21. /<0/{s/<>//gapre un blocco condizionale se una bocca non è vuota. s/<>//gcancella tutte le bocche vuote, perché quei gruppi sono troppo corti.
  22. bC continua il ciclo di contrazione.
  23. }chiude il blocco. Ora qualsiasi bocca è vuota e segna il gruppo più lungo di 0.
  24. s/<>(0:)+/:/contrae il gruppo più lungo, così :<>0:0:0:diventerebbe ::. In un pareggio, prende la bocca vuota a sinistra.
  25. s/<>//g cancella qualsiasi altra bocca vuota.
  26. /^::/!s/://cancella i primi due punti extra a meno che non faccia parte di ::.
  27. /::$/!s/:$//lo fa per gli ultimi due punti extra. Quindi sed stampa l'indirizzo IP in forma abbreviata.

1

Python 3: 387 caratteri

Funziona anche con input accorciati in modo errato.

$ echo '1::2:0:0:0:3' | python3 ipv6.py 
1:0:0:2:0:0:0:3
1:0:0:2::3

Il doppio rimpiazzo di ':::'con '::'sembra davvero pessimo, ma non è sicuro di come gestire in modo pulito la stringa più lunga di 0 quando raggiunge una o entrambe le estremità.

c=':'
p=print
try:
 B=[int(x,16)if x else''for x in input().split(c)];L=len(B)
 if any(B)-1:B=[''];L=1
 if L!=8:s=B.index('');B[s:s+1]=[0]*(9-L)
 for b in B:assert-1<b<2**16
 H=[format(x,'X')for x in B];o=c.join(H);p(o);n=''.join(str(h=='0')[0]for h in H)
 for i in range(8,0,-1):
  s=n.find('T'*i)
  if s>=0:H[s:s+i]=[c*2];p(c.join(H).replace(c*3,c*2).replace(c*3,c*2));q
 p(o)
except:0

Sostituisci il finale passcon raiseper vedere come si blocca proteggendo da input non valido.

$ cat ipv6-test.sh 
echo '1080:0:0:0:8:800:200C:417A' | python3 ipv6.py
echo '1:2:3:4:5:6:7:8' | python3 ipv6.py
echo 'FF01::101' | python3 ipv6.py
echo '0:0:0:0:0:0:0:1' | python3 ipv6.py
echo '0:0:0:0:1:0:0:0' | python3 ipv6.py
echo '1:0:0:0:0:0:0:0' | python3 ipv6.py
echo '::' | python3 ipv6.py
echo '1:0:0:2:0:0:0:3' | python3 ipv6.py
echo '1::2:0:0:0:3' | python3 ipv6.py
echo '1:0:0:8:8:0:0:3' | python3 ipv6.py
echo 'ABCD:1234' | python3 ipv6.py
echo 'ABCDE::1234' | python3 ipv6.py
echo '1:2:3:4:5:6:7:8:9' | python3 ipv6.py
echo ':::1' | python3 ipv6.py
echo 'codegolf puzzle' | python3 ipv6.py
$ ./ipv6-test.sh 
1080:0:0:0:8:800:200C:417A
1080::8:800:200C:417A

1:2:3:4:5:6:7:8
1:2:3:4:5:6:7:8

FF01:0:0:0:0:0:0:101
FF01::101

0:0:0:0:0:0:0:1
::1

0:0:0:0:1:0:0:0
::1:0:0:0

1:0:0:0:0:0:0:0
1::


0:0:0:0:0:0:0:0
::

1:0:0:2:0:0:0:3
1:0:0:2::3

1:0:0:2:0:0:0:3
1:0:0:2::3

1:0:0:8:8:0:0:3
1::8:8:0:0:3

@DigitalTrauma corretto. Stavo cercando "0: 0: 0 ..." e stava catturando gli 0 finali
Nick T,

Al giorno d'oggi non senti abbastanza la parola "abut" abbastanza
Claudiu,

Un insetto? Questo programma ha accettato 1:2:3:4::a:b:c:dma respinto sia ::2:3:4:a:b:c:de 1:2:3:4:a:b:c::. Credo che sia stato sbagliato tutte e tre le volte.
kernigh,
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.