2014年世界IPv6デー


22

世界IPv6デーの記念日をマークするために、インターネット協会はOne Dayの2014年6月6日にIPv4止めるキャンペーンを発表しました。


IPv6アドレスは、コロンで区切られた8つの16ビット16進値として長い形式で表されます。アドレスに応じて、RFC 3513セクション2.2 アドレステキスト表現の項目2で説明されているように、短縮することもできます

ゼロビットを含むアドレスの書き込みを容易にするために、ゼロを圧縮する特別な構文が利用可能です。「::」の使用は、16ビットのゼロの1つ以上のグループを示します。「::」は、アドレスに一度しか表示できません。「::」は、アドレスの先頭または末尾のゼロを圧縮するためにも使用できます。

  • このチャレンジのエントリは、長い形式または短い形式のいずれかでフォーマットされたIPv6アドレスを1つだけ受け入れ、長い形式と短い形式の両方で同じアドレスをこの順序で表示するプログラムです。

  • 入力は、コマンドライン引数、STDIN、または選択した言語に適した他の入力ソースからのものです。

  • IPv6アドレスの解析専用のライブラリまたはユーティリティは禁止されています(inet_ {ntop、pton}()など)。

  • 入力アドレスが無効な場合、出力は空になります(または、アドレスが無効であることを示す適切なエラーメッセージが表示されます

  • ::短縮が発生する場合、特定のアドレスに対して1つの短縮操作のみが発生する場合があります。特定のアドレスに対して複数の潜在的な短縮操作がある場合、全体の最短アドレスを提供する操作を使用する必要があります。この点で同点がある場合は、最初の操作が使用されます。これを以下の例に示します。

  • 回避すべき標準的な抜け穴

例:

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>

これはであるため、2014年6月6日のバイト単位の最短回答が勝者として受け入れられます。


入力がであるとし1:0:0:2:2::3ます。短縮された出力はそれと同じ1::2:2:0:0:3ですか?最適化されていない入力に対しても同じです。
マーティンエンダー

@ m.buettnerこの場合、どちらかを選んでもらいます。
デジタル外傷

1::2:0:0:0:3入力は可能ですか?
user12205


2
これは、誰もが私にipv6を習得させる唯一の方法だと思います。+1
Obversity

回答:


4

JavaScriptの(ES6) - 198183180188、187のバイト

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

そして、いくつかのポップアップ(203バイト)を備えたもう少し長いインタラクティブバージョン:

/^(:[\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))

ゴルフをしていない:

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

説明:

IPv6アドレスの長いバージョンを計算するには:

8 - str.split(/:+/).length % 9-挿入する必要があるゼロの数を計算します。それらは8-16進値の数です。ここで、%9はガードなので、負の数になることはありません。

replace('::', ':0'.repeat(zeros || 1) + ':')-「::」をコロンで区切られたゼロに置き換えます。追加するゼロがない場合でも、アドレスが最後に有効にならないように1を追加します

replace(/^:0|0:$/g, zeros ? '0:0' : '0')-これは、split関数が16進値の数に1を加算するため、アドレスが「::」で始まるまたは終わる特殊なケースを扱います(:: 1-> [""、 "1"])

それでおしまい!それでは、短い形式を計算しましょう:

replace(/(\b0(:0)*)(?!.*\1:0)/,':') -ゼロの最も長い行をコロンで置き換えます(いくつでもかまいません)。

replace(/::+/,'::') -余分なコロンがある場合は削除します

return /^(:[\da-f]{1,4}){8}$/i.test(':'+longIP) && [longIP, shortIP];-長いバージョンが有効なIPv6であるかfalseどうかをテストし、両方のバージョンを返すか、テストが失敗した場合。

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

私よりもずっといい!このような入力を処理するには、いくつかの修正が必要です:: 1:、:1 ::
edc65

これは無効なものを受け入れました1:2:3:4::a:b:c:d
カーニグ14年

6

Javascript(E6)246305284292292319

特別に処理された::の特別なケースを大幅に改訂し、圧縮フェーズはforループを回避します(しかし実際にはそれほど短くありません) 最終的な圧縮フェーズを短くすることができると確信しています。とにかく今は

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

おかげnderscore

プログラムとして

基本的にjs popupを使用した入力と出力:p=prompt,p(F(p())) ポップアップを使用して、関数定義なしで書き換えると、charカウントは260未満になります。

ゴルフ をしていないと少しコメント

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

コンソールでテスト

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

テスト出力

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

機能よりもむしろプログラムが欲しい。私は、これが可能かどうかを知るのに十分なほどJavaScriptを知りません。
デジタル外傷

@nderscoreおっと-タイプミス。新しいコメントで修正されました。
デジタル外傷

から入力を取得することで、プログラムにすることができますprompt()。290まで下げる最適化を次に示します。pastie.org
private

@nderscore:thx、最初の置換はinput = '::'に対して機能しません、とにかく素晴らしい仕事です!
edc65

@ edc65その置換の修正を見つけました:) pastie.org/private/kee0sdvjez0vfcmlvaxu8q
nderscore

4

Perl- 204176190191197

(202文字+ -pフラグの2 )

$_=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/::::?/::/

例:

$ 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

説明:

# -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
「ipv6.pl行1、<>行1で死亡しました」。これは質問のコメントで尋ねられました。メッセージがある場合、それは無効なメッセージによるものであることを明確にする必要があります。私は質問でそれを明確にしようとしました。それ以外の場合はよさそうだ!
デジタル外傷

1
@DigitalTrauma dieサイレント出口に変更されました。
mniip

1
バグ?このプログラムは無効なアドレスを受け入れます1:2:3:4::a:b:c:d。ほとんどの8コロンアドレスは無効ですが::2:3:4:a:b:c:d1:2:3:4:a:b:c::両方とも有効であるため、これは迷惑な特殊なケースです。
カーニグ14年

3

sed、276

ipshorten.sedに275バイト、さらに拡張正規表現を使用するための-rスイッチ用の1バイトがありsed -rfます。OpenBSD sed(1)を使用しました。

使用法: 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/:$//

sedは数値を比較したり配列を作成したりできないため、22個の正規表現を使用しています。入力の各行に対して、sedはコマンドを実行し、その行を出力します。テスト中、ファイルにIPアドレスの疑いのある行をいくつか入れて、このファイルをsedに送りました。拡張正規表現への参照はre_format(7)にあります。

  1. s/^/:/行の先頭に余分なコロンを追加します。この追加のコロンを使用して、次の2つのコマンドを実行します。
  2. /^(:[0-9A-Fa-f]{0,4})*$/!d行全体がコロンのゼロ以上のグループに一致するかどうかをチェックし、その後に0〜4桁の16進数が続きます。!チェックを無効にするため、d16進数が大きすぎる行や無効な文字を含む行を削除します。ときにd行を削除し、このライン上で実行されていない複数のコマンドをsedの。
  3. s/:0*([^:])/:\1/g各番号から先頭の0を削除します。に変更さ:0000:0000::0:0:ます。収縮ループは1桁の0でのみ機能するため、これを行う必要があります。
  4. s/://余分なコロンを削除します。最初のコロンのみを削除します。
  5. s/::/:=/最初の::をに変更し:=ます。これは、後でで=はなくコマンドが一致できる::ため=、コロンとしてカウントされないためです。がない場合::、この置換は安全に何もしません。
    • 今、::少なくとも一つの0を作るが、この0を配置するための3つの異なるケースがある必要があります。
  6. s/(.:=)(.)/\10:\2/最初のケースです。::が他の2つの文字の間にあった場合、に:=なり:=0:ます。これは、コロンを追加する唯一のケースです。
  7. s/^:=/0&/2番目のケースです。::行の先頭にあった場合、そこに0を入れます。
  8. s/=$/&0/::行末での3番目のケースです。
  9. :E は、拡張ループのラベルです。
  10. /(.*:){7}/!{/=/!d行のコロンが7個未満の場合、条件ブロックを開始します。コロン/=/!dがないか::、十分でないコロンを削除します。
  11. s//=0:/コロンを1つ追加します。空//は最後の正規表現を繰り返すので、これは本当にs/=/=0:/です。
  12. bE分岐し:Eてループを継続します。
  13. }ブロックを閉じます。現在、行には少なくとも7つのコロンがあります。
  14. s/=//削除し=ます。
  15. /^:|::|:$|(.*:){8}/d拡張後の最終チェックです。先頭のコロン、::展開されなかった余分な行、末尾のコロン、または8つ以上のコロンを含む行を削除します。
  16. p 行を印刷します。これは、長い形式のIPアドレスです。
  17. s/.*/:&:/ 余分なコロンでアドレスをラップします。
    • 次のタスクは、などの0の最も長いグループを見つけ:0:0:0:、に縮小すること::です。
  18. s/:((0:)+)/:<\1>/g0の各グループを食べるため、:0:0:0:になり:<0:0:0:>ます。
  19. :C は、収縮ループのラベルです。
  20. s/0:>/>0:/g各口から1つの0を移動するため、:<0:0:0:>になり:<0:0:>0:ます。
  21. /<0/{s/<>//g口が空でない場合、条件ブロックを開きます。s/<>//gそれらのグループが短すぎるため、空の口をすべて削除します。
  22. bC 収縮ループを継続します。
  23. }ブロックを閉じます。これで、すべての口が空になり、0の最も長いグループがマークされます。
  24. s/<>(0:)+/:/最長のグループと契約するため、:<>0:0:0:になり::ます。同点で、左側の空の口を選択します。
  25. s/<>//g 他の空の口を削除します。
  26. /^::/!s/://の一部でない限り、最初の余分なコロンを削除し::ます。
  27. /::$/!s/:$//最後の余分なコロンに対してそうします。次に、sedはIPアドレスを短い形式で出力します。

1

Python 3:387文字

不適切に短縮された入力でも動作します。

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

':::'with の二重置換は'::'本当に悪い感じがしますが、片方または両方の端に接するときに0の最も長い文字列をきれいに処理する方法がわかりません。

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

ファイナルpassraiseに置き換えて、不正な入力から保護してクラッシュする様子を確認します。

$ 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が修正されました。「... 0:0 0」とそれが0の末尾のキャプチャされた私が探していた
ニック・Tを

あなたは本当に十分な、今日の単語「当接して」聞こえない
クラウディウ

バグ?このプログラムは受け入れまし1:2:3:4::a:b:c:dたが、::2:3:4:a:b:c:dとの両方を拒否しました1:2:3:4:a:b:c::。3回とも間違っていたと思う。
カーニグ14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.