IPv4整数変換関数


17

IPアドレスを整数表現に変換し、整数として出力する最短の関数を作成します。

IPv4アドレスを整数表現に変更するには、次の計算が必要です。

  • IPアドレスを4つのオクテットに分割します。
  • (Octet1 * 16777216) + (Octet2 * 65536) + (Octet3 * 256) + (Octet4)

サンプル入力

192.168.1.1           10.10.104.36           8.8.8.8

サンプル出力

3232235777            168454180              134744072

2
言語の組み込み関数を禁止する制限が設けられている場合、これはより良いと思います。
ネイサンオスマン

@ジョージ-はい、そうだったでしょうが、私はそれを入れる前に人々はすでにそれをしていました-私は正直にそれについて考えませんでした。
カイル・ロゼンド

回答:





8

C:79文字

main(i,a)char**a;{i=i<<8|strtol(a[1],a+1,0);*a[1]++?main(i,a):printf("%u",i);}

編集:C ++を削除し、ヘッダーなしでコンパイルしませんでした。GCCでは、printfおよびstrtol関数呼び出しは組み込み関数をトリガーするため、ヘッダーをスキップできます。ヒントは@ugorenに送ってください。これは、追加オプションなしでそのままコンパイルされますgcc

EDIT2:return実際には冗長です:)


main()の非常に巧妙な使用:) ..私のバージョンは116バイトでした。
アキラ

セグメンテーション違反が発生します。
ネイサンオスマン

@George、あなたの入力は何ですか、それをどのように実行していますか?
ニム

私はを通じて私のUserScriptでそれを実行しているcodepad.org
ネイサン・オスマン

これはC ++では機能せず、mainを再帰的に呼び出すことはできません。
スコットローガン

7

Golfscript-16文字

{[~]2%256base}:f

スタンドアロンプ​​ログラムとして、これは11でさらに短くなります。

~]2%256base

非常に簡単です。入力文字列(~)を評価し、配列に入れ[]ます。.文字列内のsはスタックの最上部を複製するため、配列(2%)の他のすべての項のみを使用します。これで基本的に256を基数とする配列ができたので、組み込み関数を使用して変換を行います。(256base)。


非常に賢い。base256は、base10またはbase16と言うように異なる方法で処理され、48 => 0ですか?
ニブラー

@gnibbler:あなたが何を提案しているのか分かりません-ベース関数はすべてのベースを同じ方法で処理します{:B;{\B*+}*}:base(例えば、実際の関数は変換のためにオーバーロードされますが)。興味深いことに、文字列のベース変換は配列と同じです(文字列は入れ子のない単なる配列ですが、出力形式は異なります)。
ナブ

ええ、私は文字列の基本変換を考えていたのでbase、私は答えを十分に見ていませんでした
-gnibbler

非常に賢い。次に、IPv6アドレスに対してこれを行います。:)
イルマリカロネン

6

Befunge-2x11 = 22文字

近いうちに、Befungeがいつか勝ちます。

>&+~1+#v_.@
^*4*8*8<

説明

Befungeの最大の特徴は、ほとんどの言語のような線形の命令セットではなく、それは、制御が任意の方向に流れることができる単一文字命令の2Dグリッドです。

>      v
^      <

これらのキャラクターは、ヒットすると制御の方向を変更します。これにより、メインループが形成されます。

 &+~1+

これは、数値を入力してスタックにプッシュし(&)、スタックから上位2つの値をポップし、それらを追加してスタックにプッシュし直し(+)、単一の文字を入力し、そのASCII値をスタックに配置します(~)、 1をスタックにプッシュして追加します(1+)。

私が使用しているインタープリターは、入力の終わりに-1を返し、代わりに0を返すため、1+一部はそれらのために削除されます。

      #v_.@

これ#により、次の文字がスキップさ_れ、スタックから値がポップされ、ゼロの場合はコントロールが右に送信され、そうでない場合は左に送信されます。値がゼロの場合、値を.スタックからポップし、整数として出力し@てプログラムを停止します。それ以外の場合vは、制御を戻りループに送ります。

^*4*8*8<

これは単にスタックの最上位値に256を掛けて、制御を最初に戻します。


私の無知を許しますが、それは19文字でなければなりませんか?なぜ2x11と言うのかは理解できますが、なぜそのように機能するのですか?
カイル・ロゼンド

Befungeは、>v<^実際にこのプログラムのメインループであるものを探す場合、2D言語です。この場合、コントロールは実際には下部の最後の3つのスペースを通過しませんが、Befungeプログラムを最小の境界矩形として数えるのが最も簡単だと思います。また、制御フローを試して数えると、自己修正プログラムで問題が発生します。
Nemo157

5

ルビー(40)

q=->x{x.gsub(/(\d+)\.?/){'%02x'%$1}.hex}

->

q["192.168.1.1"]
=> 3232235777

正規表現を使用する良いアイデア。
-Hauleth

非常に賢い!また、あなたは書くことができるto_i 16ようhex、いくつかの文字を保存します。
ポール・プレスティッジ

両方これと作られたおかげ@chron リンク 4文字が短い
jsvnm


3

Golfscript-21文字

{'.'/{~}%{\256*+}*}:f

+1良好な固溶体。GolfScriptがビットシフト演算子を提供することを望みませんか?;-)(ただし、私は彼らにバインドされるべきシンボルを知っていればとびきり。)
クリス・ジェスター・ヤング


3

C ++-たくさんの文字

#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
uint f(std::string p)
{
        std::vector<std::string> x;
        boost::split(x,p,boost::is_any_of("."));
        uint r=0;
        for (uint i = 0; i < x.size(); i++)
                r=r*256+atoi(x[i].c_str());
        return r;
}

@George Edison:ブーストを使用すると、文字数を減らすのに役立ちますか?:)
アキラ

3

PowerShell 66 61

ジョーイの答えのバリエーション:

filter I{([ipaddress](($_-split'\.')[3..0]-join'.')).address}

PS C:\> '192.168.1.1' | I
3232235777
PS C:\> '10.10.104.36' | I
168454180
PS C:\> '8.8.8.8' | I
134744072

ああ、私はそれを見逃したのは愚かだったに違いない...-
ジョーイ

3

〜47文字のAWK

最初のタイマー...これを数える方法はわかりませんが、「エコー」がなければ、AWKでは47文字になります。(正確にはボギーゴルフではありませんが、穴の中にあります。)

echo $addr | /bin/awk -F\. '{print $1*16777216+$2*65536+$3*256+$4}'

#tbtの1日も早いので、実際にスケジュールを満たしました!!! * 8-)

バナーの日。


1
ようこそ!awkスクリプトに入れたものの本文のみを数えます。この回答をご覧ください。あなたの場合、あなたは数えるだけでしょう{print $1*16777216+$2*65536+$3*256+$4}。もちろん、フラグとして指定するのではなく、フィールドセパレータをプログラムに移動する必要があります。
ジョナ

3

バッシュ-46

目次

4つの異なるゴルフバージョンがあります。

echo $[_=32,`printf "%d<<(_-=8)|" ${1//./ }`0]                        # 46chr
set -- ${1//./ };echo $[$1<<24|$2<<16|$3<<8|$4]                       # 47chr
v=('|%d<<'{24,16,8,0});printf -vv "${v[*]}" ${1//./ };echo $[0$v]     # 65chr
mapfile -td. i<<<$1;for((a=o=0;a<4;o+=i[a]<<(3-a++)*8)){ :;};echo $o  # 68chr

新しいバージョン!2018-11-15さらにゴルフ、46文字

echo $[_=32,`printf "%d<<(_-=8)|" ${1//./ }`0]

説明

  • $_はより多くのゴ​​ルフに使用しました。
  • 構文${1//./ }は、すべてのドット.をスペースで置き換えます
  • のようprintfなものをレンダリングします192<<(_-=8)|168<<(_-=8)|1<<(_-=8)|1<<(_-=8)|
  • その後0、最後のORを追加します |
  • プリセット_32は左から右にコンストラクトを読み取る$((_-=8))ため24、1番目のシフト16、2番目のシフトで、というように続きます。

動作中:

set -- 192.168.1.1
echo $[_=32,`printf "%d<<(_-=8)|" ${1//./ }`0]
3232235777

楽しみのために:$_この後、コンテンツを取得しようとしています:

echo $_
3232235777

; -b

set -- 192.168.1.1
echo $_ $[_=32,`printf "%d<<(_-=8)|" ${1//./ }`0] $_
192.168.1.1 3232235777 0

はい、それは正しいです 32 - 4 x 8 = 0

関数内:

ip2int() {
    echo $[_=32,`printf "%d<<(_-=8)|" ${1//./ }`0]
}
ip2int 192.168.1.1
3232235777
ip2int 255.255.255.255
4294967295
ip2int 0.0.0.0
0

またはループに:-> 60

ip2int() {
    for i;do
        echo $[_=32,`printf "%d<<(_-=8)|" ${i//./ }`0]
    done
}

ip2int 192.168.1.1 10.10.104.36 8.8.8.8 1.1.1.1 255.255.255.255 0.0.0.0
3232235777
168454180
134744072
16843009
4294967295
0

バッシュ(v4.1 +):47

最初の投稿

set -- ${1//./ };echo $[$1<<24|$2<<16|$3<<8|$4]

説明:

  • 構文${1//./ }は、すべてのドット.をスペースで置き換えます
  • set --位置パラメーターの設定$@=($1 $2 $3...)
  • だから、set -- ${1//./ }分割されます$1ドットとセットで$1$2$3および$4文字列containg場合3、ドット(スペースなし)。

動作中:

set -- 192.168.1.1
set -- ${1//./ };echo $[$1<<24|$2<<16|$3<<8|$4]
3232235777

または関数内:

ip2int() {
    set -- ${1//./ }
    echo $[$1<<24|$2<<16|$3<<8|$4]
}
ip2int 192.168.1.1
3232235777
ip2int 0.0.0.0
0

またはループに:-> 61

for i;do set -- ${i//./ };echo $[$1<<24|$2<<16|$3<<8|$4];done

動作中:

ip2int() {
    for i;do
        set -- ${i//./ }
        echo $[$1<<24|$2<<16|$3<<8|$4]
    done
}

ip2int 192.168.1.1 10.10.104.36 8.8.8.8 1.1.1.1 0.0.0.0
3232235777
168454180
134744072
16843009
0

別のゴルフのバージョン:65

v=('|%d<<'{24,16,8,0});printf -vv "${v[*]}" ${1//./ };echo $[0$v]

サンプル:

ip2int() {
    v=('|%d<<'{24,16,8,0});printf -vv "${v[*]}" ${1//./ };echo $[0$v]
}

ip2int 255.255.255.255
4294967295
ip2int 10.10.104.36
168454180

ループ内(+14):82

ip2int() {
    for i;do
        v=('|%d<<'{24,16,8,0})
        printf -vv "${v[*]}" ${1//./ }
        echo $[0$v]
    done
}

*またはもう少しい:70 *

v=('|%d<<'{24,16,8});printf -vv "${v[*]}" ${1//./ };echo $[0${v%<<2*}]

ここで、最後にカットする必要があるprintfような文字列|192<<24 |168<<16 |1<<8|1<<24 |0<<16 |0<<8を指定します<<2...

でゴルフmapfile、長い:68

ip2int() {
    mapfile -td. i<<<$1;for((a=o=0;a<4;o+=i[a]<<(3-a++)*8)){ :;};echo $o
}

またはループ付き:82

ip2int() {
    for a;do
      mapfile -td. i<<<$a;for((a=o=0;a<4;o+=i[a]<<(3-a++)*8)){ :;};echo $o
    done
}

簡単な説明を追加できますか?私はゴルフをバッシュに取り込もうとしていますが、そのset --部分で何が起こっているのかを追跡していません。ありがとう。
ジョナ

@Jonah:foo as およびbar as set -- foo barを入力$@ます$1$2
F.ハウリ

@Jonah追加新バージョン
F. HAURI

説明してくれてありがとう。
ジョナ

新しいバージョン!もっとゴルフ、-1文字!!
F.ハウリ

2

Windows PowerShell、70

ナイーブアプローチ:

filter I{[int[]]$x=$_-split'\.'
$x[0]*16MB+$x[1]*64KB+$x[2]*256+$x[3]}

System.Net.IPAddressを使用した場合:76

filter I{([ipaddress]($_-replace('(.+)\.'*3+'(.+)'),'$4.$3.$2.$1')).address}

テスト:

> '192.168.1.1'|I
3232235777


2

Perl:DIY(oneliners向け)(40)

$j=3;$i+=($_<<($j--*8))for split/\./,$x;

#$ iの値を使用

DIY機能(65):

sub atoi{my($i,$j)=(0,3);$i+=($_<<($j--*8))for split'.',shift;$i}

文字列で分割することができますので、split'.'ではなくを使用して文字を保存するsplit/\./
匿名

関数バージョンでは、はい、しかしインラインバージョンではありません。split q{.}シェルの引用符をエスケープする必要性を回避する必要があるからです:/
Kent Fredric

2

Haskell-14文字

(.) a=(256*a+)

GHCiでの使用:

Prelude> let (.) a=(256*a+)
Prelude> 192. 168. 0. 1
3232235521

唯一の問題は、ドットの左右にスペースを入れなければならないことです。そうしないと、数値は浮動小数点として解釈されます。


簡単な説明を追加してもいいですか?
ジョナ

ドット挿入演算子は計算を行うために再定義されており、実にスマートです!
メモ

これは非常に巧妙ですが、正しい入力形式を使用しません(スペースのため)
12Me21


2

JavaScript(45文字)

.reduce()ES5で導入されたArrayメソッドと矢印関数のサポートが必要です。

f=(x)=>x.split('.').reduce((p,c)=>p<<8|c)>>>0

ええと…私は知らなかった>>>そのように働いた(符号なし32ビット整数に変換する)
12Me21

2

Powershell、47 43バイト

$args-split'\.'|%{$r=([long]$r-shl8)+$_};$r

テストスクリプト:

$f = {

$args-split'\.'|%{$r=([long]$r-shl8)+$_};$r

}

@(
    ,("192.168.1.1",3232235777)
    ,("10.10.104.36",168454180)
    ,("8.8.8.8",134744072)
) | % {
    $s,$expected = $_
    $result = &$f $s
    "$($result-eq$expected): $result"
}

出力:

True: 3232235777
True: 168454180
True: 134744072

1

C#-120文字

float s(string i){var o=i.Split('.').Select(n=>float.Parse(n)).ToList();return 16777216*o[0]+65536*o[1]+256*o[2]+o[3];}

私の最初のコードゴルフ-優しくしてください;)


最初の「=」の前後のスペースを削除できます。ただし、主な問題はintオーバーフローです;)。IPアドレスは4バイトを占有することを忘れないでください。
ネリウス

@Nellius-まったくその通り。私はそれをチェックすることすら考えていませんでした。基本的にはコンパイル時にチェックされていました。ありがとう、今修正します。
カイル・ロゼンド

1

D:84文字

uint f(S)(S s)
{
    uint n;
    int i = 4;

    foreach(o; s.split("."))
        n += to!uint(o) << 8 * --i;

    return n;
}

Dがわからないので、Pythonのようなホワイトスペースに敏感であれば許してくれますが、これはゴルフのようには見えません。セミコロンで終了したステートメント間の二重改行または改行を削除できますか?
ジョナ

1

Python 3.2(69)

sum((int(j)*4**(4*i)) for i,j in enumerate(input().split('.')[::-1]))

1

PHP(組み込み/評価なし)-54

<foreach(explode(".",$argv[1])as$b)$a=@$a<<8|$b;echo$a;

これ<?phpだけでなく、これを開いてはいけません<か?
TRiG

@TRiG、設定ファイルでPHPの開始区切り文字を変更できると思います。この場合に便利です。
Xeoncross

@Xeoncross。あ。きちんとした。いつか、同僚の頭をいじってみようと思うかもしれません。
TRiG





弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.