IPv4整数转换功能


17

编写最短函数以将IP地址转换为它的整数表示形式并将其输出为整数。

要将IPv4地址更改为其整数表示形式,需要进行以下计算:

  • 将IP地址分成四个字节。
  • (Octet1 * 16777216) + (Octet2 * 65536) + (Octet3 * 256) + (Octet4)

样本输入

192.168.1.1           10.10.104.36           8.8.8.8

样本输出

3232235777            168454180              134744072

2
我认为如果对语言的内置功能有限制的话,这样做会更好。
内森·奥斯曼

@George-是的,应该这样,但是人们在我可以输入之前就已经做到了-老实说我没有考虑过。
凯尔·罗曾多

Answers:




8

Ruby(无内置功能/评估版)-47

s=->s{s.split(".").inject(0){|a,b|a<<8|b.to_i}}

测试:

s["192.168.1.1"]
3232235777

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 ++,没有标题就无法编译;与海湾合作委员会,printfstrtol函数调用会触发内置函数,因此可以跳过标头。谢谢@ugoren。它将按原样编译,而没有其他选项gcc

EDIT2:return实际上是多余的:)


main():)的非常聪明的用法..我的版本是116bytes。
akira

我遇到了细分错误。
内森·奥斯曼

@George,您的输入是什么,如何运行它?
尼姆,

我正在通过codepad.org
Osman

这在C ++中不起作用,您不能递归调用main。
Scott Logan '02

7

Golfscript-16个字符

{[~]2%256base}:f

作为一个独立程序,它甚至更短为11。

~]2%256base

非常简单。计算输入字符串(~)并将其放入数组中[]。由于.字符串中的s重复了堆栈的顶部,因此我们仅将数组(2%)中的所有其他项作为接受项。现在,我们有了一个数组,该数组基本上表示一个以256为基数的数字,因此我们使用内置函数进行转换。(256base)。


非常聪明。我猜base256被不同地说成base10或base16,那么其中48 => 0?
gnibbler 2011年

@gnibbler:我不确定您的建议是什么-基本函数以相同的方式处理所有基础,例如{:B;{\B*+}*}:base(尽管实函数对于转换是重载的)。有趣的是,字符串的基本转换与数组相同(因为字符串只是没有嵌套但具有不同输出格式的数组)。
Nabb 2011年

是的,我当时正在考虑字符串的基本转换,所以我base对答案的关注度不够
gnibbler 2011年

非常聪明。现在对IPv6地址执行此操作。:)
Ilmari Karonen

6

Befunge-2x11 = 22个字符

如此接近,Befunge将赢得一天。

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

说明

Befunge最大的区别在于,它不是像大多数语言一样线性的指令集;它是一个单字符指令的2d网格,其中控制可以沿任何方向流动。

>      v
^      <

这些字符在被击中时会改变控制方向,从而形成主循环。

 &+~1+

这将输入一个数字并将其压入堆栈(&),从堆栈中弹出顶部的两个值,将它们相加并将其压回堆栈(+),输入一个字符并将其ascii值放在堆栈上(~),然后将1压入堆栈并添加(1+)。

我一直使用的解释器在输入结束时返回-1,有些则返回0,因此1+可以为他们删除该部分。

      #v_.@

#使下一个字符被跳过,则_弹出从堆栈的值,并且,如果它是零发送控制权,否则将其发送离开。如果该值为零.,则将一个值弹出堆栈,然后将其输出为整数并@停止程序。否则v将控制权发送到返回回路。

^*4*8*8<

这只是将堆栈的最高值乘以256,然后将控制权返回到起始位置。


请原谅我的无知,但那应该是19个字符吗?我了解您为什么说2x11,但是为什么这样工作?
凯尔·罗岑多

如果您寻找Befunge是2D语言,则>v<^它实际上是该程序中的主循环。我想在这种情况下,控件实际上并没有经过底部的最后3个空格,但是我发现将Befunge程序视为最小的边界矩形是最容易的。如果您要尝试计算控制流,就会遇到自我修改程序的麻烦。
Nemo157



3

Golfscript-21个字符

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

+1好的固溶体。您不希望GolfScript提供移位操作符吗?;-)(不过,如果我不知道它们应该绑定到哪个符号,该死的。)
Chris Jester-Young


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):使用boost有助于减少字符数?:)
akira

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

哎呀,我一定很愚蠢,错过了这一点……
Joey

3

AWK,约47个字符

第一次来这里...嗯,不知道如何计算,但是没有'echo',它在AWK中是47个字符。(不完全是柏忌高尔夫,但它在洞里。)

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

#tbt也很早,所以我实际上遇到了时间表!* 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在第一次转变16在第二次,依此类推。

实际上:

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

bash(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如果字符串方含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
}

你能补充一个简短的解释吗?我一直试图参加bash打高尔夫球,但我不了解该set --零件的情况。谢谢。
乔纳

@Jonah:set -- foo bar将填充$@$1酒吧$2
F. Hauri

@Jonah添加了新版本
F. Hauri

感谢您的解释。
乔纳

新版本!打更多的球,-1个字符!!
F. Hauri

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

Befunge-93-36个字符

&"~"2+::8****&884**:**&884***&++++.@

2

Perl:DIY(用于单行)。(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/\./
匿名co

函数版本为是,但内联版本为否,因为您split q{.}需要避开对shell引号进行转义的需要:/
Kent Fredric

2

Haskell-14个字符

(.) a=(256*a+)

GHCi中的用法:

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

唯一的问题是,您必须在点的左侧或右侧放置空格,否则数字将被解释为浮点数。


介意加一个简短的解释?
乔纳

重新定义了点缀运算符以进行计算,确实非常聪明!
备忘录

这非常聪明,但是它没有使用正确的输入格式(由于空格)
12Me21,19:39

2

C#– 77个字符

Func<string,uint>F=s=>s.Split('.').Aggregate(0u,(c,b)=>(c<<8)+uint.Parse(b));

2

JavaScript(45个字符)

需要支持.reduce()ES5中引入的Array方法和箭头函数

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

......我不知道>>>是那样工作的(转换为无符号的32位整数)
12Me21,15

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

@Nellius-非常正确。我什至没有想到要检查,基本上检查编译。谢谢,将立即修复。
Kyle Rozendo'2

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 2012年

@TRiG,我相信您可以在配置文件中更改PHP开头分隔符。在这种情况下很有用。
Xeoncross 2012年

@Xeoncross。啊。整齐。我可能会尝试这一天,只是为了弄乱同事们的头。
TRiG 2012年

1

Perl,14个字符:

sub _{unpack'L>',pop}

# Example usage
print _(10.10.104.36) # prints 168454180

5
您如何制作这14个字符?我数21。–
彼得·泰勒




By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.