すべての有効なクラスフルパブリックユニキャストIPv4アドレスを出力します


10

IPv4アドレスは32ビット幅であるため、アドレス空間のサイズは2 32、つまり4,294,967,296です。ただし、これは理論上の上限にすぎません。これは、実際に公衆インターネットで使用される可能性があるすべてのアドレスを正確に表したものではありません。

この課題では、すべてのアドレス指定がクラスフルであると想定されています。実際には、アドレス空間のクラス分けはCIDR(Classless Inter-Domain Routing and VLSM(Variable Length Subnet Masking))に取って代わられましたが、これはこの課題では無視されます。

クラスフルアドレススキームによれば、3つのクラスがあります。

  • クラスA - 0.0.0.0127.255.255.255/8ネットマスク長
  • クラスB - 128.0.0.0191.255.255.255/16ネットマスク長
  • クラスC - 192.0.0.0223.255.255.255/24ネットマスク長

クラスD(マルチキャスト)およびE(予約済み)も定義されていますが、これらはパブリックユニキャストアドレスには使用されません。

各クラスは、そのクラスのネットマスクに従ってネットワークに分割されます。

したがって3.0.0.0、クラスAネットワークの例です。クラスAのネットマスク長が8であるので、このネットワークのための完全なアドレス空間がある3.0.0.03.255.255.255。ただし、最初のアドレス(3.0.0.0)はネットワークアドレスとして予約され、最後のアドレス(3.255.255.255)はそのネットワークのブロードキャストアドレスとして予約されています。したがって、使用可能なアドレスの実際の範囲は3.0.0.13.255.255.2542である24 - 2(= 16777214)合計アドレス。

同様に、200.20.30.0クラスCネットワークの例です。クラスCのネットマスク長が24であるので、このネットワークのための完全なアドレス空間がある200.20.30.0200.20.30.255。ネットワークブロードキャストアドレスの葉を使用可能なアドレスの実際の範囲を除去することである200.20.30.1200.20.30.254その2 8 2(= 254)合計アドレス- 。

パブリックユニキャストに使用できるアドレス範囲には、さらに制限があります。RFC 6890によると、許可されない範囲は次のとおりです。

  • 0.0.0.0/8 -ローカルネットワーキング
  • 10.0.0.0/8 -私的使用
  • 100.64.0.0/10 -共有アドレス空間
  • 127.0.0.0/8 -ループバック
  • 169.254.0.0/16 -ローカルリンク
  • 172.16.0.0/12-私的使用
  • 192.0.0.0/24 -IETFプロトコルの割り当て
  • 192.0.2.0/24 -ドキュメントでの使用のために予約済み
  • 192.88.99.0/24 -6to4リレーエニーキャスト
  • 192.168.0.0/16 -私的使用
  • 198.18.0.0/15 -ベンチマーク
  • 198.51.100.0/24 -ドキュメントでの使用のために予約済み
  • 203.0.113.0/24 -ドキュメントでの使用のために予約済み

上記のリストでは、VLSRネットマスクを使用して範囲を効率的に指定していることに注意してください。1つを除くすべてのケースで、指定されたマスク長の特異性は、範囲の最初の通常のクラスフルマスク長以下です。したがって、これらの各VLSR範囲は、1つ以上のクラスフルネットワークと同等です。例えば、172.16.0.0/12クラスBのネットワークに相当する172.16.0.0まで172.31.0.0、またはアドレス範囲172.16.0.0172.31.255.255

このルールの例外は100.64.0.0/10VLSR範囲で、これは包含100.0.0.0クラスA範囲よりも具体的です。したがって100.0.0.0、中央に4,194,304アドレスホールがあることを除いて、他のクラスA範囲と同様に処理されます。このクラスAの範囲内の有効アドレスがあろう 100.0.0.0100.63.255.255100.128.0.0する100.255.255.2542の合計、24 2 - 22 - 2(= 12582910)合計アドレス。

この課題の目標は、パブリックインターネットホストに有効に割り当てられる可能性のあるすべてのクラスA、B、CのユニキャストIPv4アドレスを出力することです(つまり、上記のアドレスを除く)。

  • 入力は行われず、予期されるべきではありません。

  • 出力は、配列、リスト、区切り文字列など、言語に適した任意の形式にすることができます。アドレスは、標準のドット付き10進形式で出力する必要があります。

  • 出力順序は関係ありません。

  • 必要なアドレス範囲を明確に指定するビルトインは許可されていません。同様に、パブリックインターネットのBGP(または他のプロトコル)ルーティングテーブルを動的に検査する方法はすべて許可されません。

数値的に最も低いアドレスは1.0.0.1、数値的に最も高いアドレスはになります223.255.255.254


この課題は、「すべてのIPv6アドレス印刷する」と似ていますが、制限があるため、明らかに異なる実装が必要です。

回答:


2

PowerShell、648 641 625バイト

for([uint64]$a=16MB;$a-lt2GB-16mb;$a++){if(($a%16mb)*(($a+1)%16mb)*($a-lt160MB-or$a-gt176MB)*($a-lt1604MB-or$a-ge1608MB)){([ipaddress]$a).IPAddressToString}}
for($a=2GB;$a-lt3GB;$a++){if(($a%64kb)*(($a+1)%64kb)*($a-lt2785152kb-or$a-gt2720mb)*($a-lt2753mb-or$a-gt2754mb)){([ipaddress]$a).IPAddressToString}}
for($a=3221225728;$a-lt3.5GB;$a++){if(($a%256)*(($a+1)%256)*(($a-lt3221225984-or$a-gt3221226240))*(($a-lt3227017984-or$a-gt3151385kb))*(($a-lt3156480kb-or$a-gt3156544kb))*(($a-lt3245184kb-or$a-gt3245312kb))*(($a-lt3247321kb-or$a-gt3325256959))*(($a-lt3405803776-or$a-gt3405804032))){([ipaddress]$a).IPAddressToString}}

編集1-残りの2の累乗演算子をすべて使用して、さらに7バイト節約しました。
編集2- [uint64]最初の宣言にキャストを移動し、$a16バイトを節約した他の2つの再キャストを削除しました。

クラスA /クラスB /クラスCの3行。読みやすくするために、別々の行として残してあります。;-)

何が起こっているのかを理解するための2つの重要なポイント:

  • PowerShellには2のべき乗演算子がありKB, MB, GBます。たとえば、intとして4KB返さ4096れます。これを複数の場所で活用して、数十バイトを削ります。
  • .NET [ipaddress]クラスは、数値のバイナリ表現を使用して、数値をIPアドレスとして解析しようとします。そのコンストラクターをIPAddressToString引数として出力に使用します。

これら2つを組み合わせると、IPアドレスを数値として扱い、ループでループすることができfor()ます。例えば、クラスAサブネットのための第一のループから行く16MBまで2GB-16MB、又はより16777216213070643216777216is のバイナリ表現は100000000000000000000000000000001.00000000.00000000.00000000それを8ビットのチャンクに分割した場合1.0.0.0、ドット付き10進表記で対応するものを簡単に確認できます。同様に、またはまたは2130706432と書くことができます。ここで使用される各整数、または2の累乗の整数は、この方法でIPアドレスとして書き換えることができます。0111111100000000000000000000000001111111.00000000.00000000.00000000127.0.0.0

したがって、ループを繰り返すたびにif()、個々のステートメントを掛け合わせて、除外されたアドレスを取り除くステートメントを作成します。それぞれの最初のステートメントifは整数(モジュロテストのおかげ)であるため、残りのブール値はfalseまたはtrueのいずれ01に変換されます。ステートメントのいずれかがfalseの場合、乗算全体がになり0、したがってfalseになります。したがって、すべてのステートメントが真である場合にのみ、解析結果を出力します。

少しゴルフをしない:

# Class A
for($a=16MB;$a-lt2GB-16mb;$a++){
  $b=($a%16mb)                     # x.0.0.0
  $b*=(($a+1)%16mb)                # x.255.255.255
  $b*=($a-lt160MB-or$a-gt176MB)    # 10.0.0.0/8
  $b*=($a-lt1604MB-or$a-ge1608MB)  # 100.64.0.0/10
  if($b){([ipaddress]::Parse($a)).IPAddressToString}
}

# Class B
for($a=2GB;$a-lt3GB;$a++){
  $b=($a%64kb)                           # x.y.0.0
  $b*=(($a+1)%64kb)                      # x.y.255.255
  $b*=(($a-lt2785152kb-or$a-gt2720mb))  # 169.254.0.0/16
  $b*=(($a-lt2753mb-or$a-gt2754mb))      # 172.16.0.0/12
  if($b){([ipaddress]::Parse($a)).IPAddressToString}
}

# Class C
for($a=3221225728;$a-lt3.5GB;$a++){
  $b=($a%256)                               # x.y.z.0
  $b*=(($a+1)%256)                          # x.y.z.255
  $b*=(($a-lt3221225984-or$a-gt3221226240)) # 192.0.2.0/24
  $b*=(($a-lt3227017984-or$a-gt3151385kb)) # 192.88.99.0/24
  $b*=(($a-lt3156480kb-or$a-gt3156544kb)) # 192.168.0.0/16
  $b*=(($a-lt3245184kb-or$a-gt3245312kb)) # 198.18.0.0/15
  $b*=(($a-lt3247321kb-or$a-gt3325256959)) # 198.51.100.0/24
  $b*=(($a-lt3405803776-or$a-gt3405804032)) # 203.0.113.0/24
  if($b){([ipaddress]::Parse($a)).IPAddressToString}
}

1

バッチ、1930 1884 1848 1830バイト

@echo off
for /l %%a in (1,1,9)do call:a1 %%a
for /l %%a in (11,1,99)do call:a1 %%a
for /l %%b in (0,1,63)do call:a2 100 %%b
for /l %%b in (128,1,255)do call:a2 100 %%b
for /l %%a in (101,1,126)do call:a1 %%a
for /l %%a in (128,1,168)do call:b1 %%a
for /l %%b in (0,1,253)do call:b2 169 %%b
call:b2 169 255
call:b1 170
call:b1 171
for /l %%b in (0,1,15)do call:b2 172 %%b
for /l %%b in (32,1,255)do call:b2 172 %%b
for /l %%a in (173,1,191)do call:b1 %%a
call:c3 192 0 1
for /l %%c in (3,1,255)do call:c3 192 0 %%c
for /l %%b in (1,1,87)do call:c2 192 %%b
for /l %%c in (0,1,98)do call:c3 192 88 %%c
for /l %%c in (100,1,255)do call:c3 192 88 %%c
for /l %%b in (89,1,167)do call:c2 192 %%b
for /l %%b in (169,1,255)do call:c2 192 %%b
for /l %%a in (193,1,197)do call:c1 %%a
for /l %%b in (0,1,17)do call:c2 198 %%b
for /l %%b in (20,1,50)do call:c2 198 %%b
for /l %%c in (0,1,99)do call:c3 198 51 %%c
for /l %%c in (101,1,255)do call:c3 198 51 %%c
for /l %%b in (52,1,255)do call:c2 198 %%b
for /l %%a in (199,1,202)do call:c1 %%a
for /l %%c in (0,1,112)do call:c3 203 0 %%c
for /l %%c in (114,1,255)do call:c3 203 0 %%c
for /l %%b in (1,1,255)do call:c2 203 %%b
for /l %%a in (204,1,223)do call:c1 %%a
exit/b
:a1
for /l %%b in (0,1,255)do call:a2 %1 %%b
exit/b
:a2
for /l %%c in (0,1,255)do call:a3 %1 %2 %%c
exit/b
:a3
for /l %%d in (0,1,255)do if not %2%3%%d==000 if not %2%3%%d==255255255 echo %1.%2.%3.%%d
exit/b
:b1
for /l %%b in (0,1,255)do call:b2 %1 %%b
exit/b
:b2
for /l %%c in (0,1,255)do call:b3 %1 %2 %%c
exit/b
:b3
for /l %%d in (0,1,255)do if not %3%%d==00 if not %3%%d==255255 echo %1.%2.%3.%%d
exit/b
:c1
for /l %%b in (0,1,255)do call:c2 %1 %%b
exit/b
:c2
for /l %%c in (0,1,255)do call:c3 %1 %2 %%c
exit/b
:c3
for /l %%d in (1,1,254)do echo %1.%2.%3.%%d

編集:不要なスペースを削除して46 82バイトを節約しました。のexit/b代わりにを使用して18バイトを節約しましたgoto:eof


1
1872バイトを数えます。あなたは、技術的に必要としない@echo offだけでなく、。
Addison Crump

@FlagAsSpamおそらくCR。メモ帳はそれらを保存するのが好きです。
Neil、

私たちはUnix UTF-8バイトで数えるので、あなたはそれらを取り除くことができると思います。
Addison Crump
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.