ฟังก์ชันการแปลง IPv4 Integer


17

เขียนฟังก์ชั่นที่สั้นที่สุดเพื่อแปลงที่อยู่ IP ให้เป็นจำนวนเต็มแทนและส่งออกเป็นจำนวนเต็ม

ในการเปลี่ยนที่อยู่ IPv4 เป็นการแสดงจำนวนเต็มการคำนวณต่อไปนี้เป็นสิ่งจำเป็น:

  • แบ่งที่อยู่ IP ออกเป็นสี่ octet
  • (Octet1 * 16777216) + (Octet2 * 65536) + (Octet3 * 256) + (Octet4)

ตัวอย่างอินพุต

192.168.1.1           10.10.104.36           8.8.8.8

ตัวอย่างผลลัพธ์

3232235777            168454180              134744072

2
ฉันคิดว่าสิ่งนี้จะดีกว่าถ้ามีข้อ จำกัด ในการห้ามฟังก์ชั่นในตัวของภาษา
Nathan Osman

@ George - ใช่แล้วมันน่าจะเป็นไปได้ แต่ผู้คนได้ทำไปแล้วก่อนที่ฉันจะใส่มันเข้าไป - ฉันไม่ได้คิดเกี่ยวกับเรื่องนี้โดยสุจริต
Kyle Rozendo

คำตอบ:





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 () :) ฉลาดมาก .. เวอร์ชันของฉันคือ 116bytes
กิระ

ฉันได้รับข้อผิดพลาดการแบ่งส่วน
นาธานออสมัน

@ George สิ่งที่คุณป้อนเข้ามาและคุณใช้มันอย่างไร?
Nim

ผมทำงานกับ UserScript ของฉันผ่านcodepad.org
นาธานออสมัน

สิ่งนี้จะไม่ทำงานใน C ++ คุณไม่สามารถเรียกหลักแบบเรียกซ้ำ
Scott Logan

7

Golfscript - 16 ตัวอักษร

{[~]2%256base}:f

ในฐานะที่เป็นโปรแกรมเดี่ยวมันก็ยิ่งสั้นลงที่ 11

~]2%256base

ตรงไปตรงมามาก ประเมินสตริงอินพุท ( ~) []และทำให้มันเป็นอาร์เรย์ เนื่องจาก.s ในสตริงซ้ำด้านบนสุดของสแต็กเราจึงรับเทอมอื่น ๆ ในอาร์เรย์ ( 2%) ตอนนี้เรามีอาเรย์ซึ่งโดยทั่วไปจะหมายถึงตัวเลขฐาน 256 ดังนั้นเราจึงใช้ฟังก์ชันในตัวเพื่อทำการแปลง ( 256base)


ฉลาดมาก. ฉันเดา base256 ได้รับการปฏิบัติที่แตกต่างกันว่า base10 หรือ base16 แล้ว 48 => 0?
gnibbler

@gnibbler: ฉันไม่แน่ใจว่าสิ่งที่คุณกำลังแนะนำ - ฟังก์ชั่นพื้นฐานจัดการฐานทั้งหมดในลักษณะเดียวกันเช่น{:B;{\B*+}*}:base(แม้ว่าฟังก์ชั่นจริงมากเกินไปสำหรับการแปลงในทางอื่น ๆ ) สิ่งที่น่าสนใจคือการแปลงฐานสำหรับสตริงเหมือนกับอาร์เรย์ (เนื่องจากสตริงเป็นเพียงอาร์เรย์โดยไม่ซ้อนกัน แต่มีรูปแบบเอาต์พุตอื่น)
Nabb

ใช่ฉันคิดของการแปลงฐานของสตริงดังนั้นฉันไม่ได้มองอย่างใกล้ชิดพอbaseสำหรับคำตอบของฉัน
gnibbler

ฉลาดมาก. ตอนนี้ทำเพื่อที่อยู่ IPv6 :)
Ilmari Karonen

6

Befunge - 2x11 = 22 ตัวอักษร

ใกล้ Befunge จะชนะวันหนึ่ง

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

คำอธิบาย

คุณสมบัติที่โดดเด่นที่สุดของBefungeคือแทนที่จะเป็นชุดคำสั่งเชิงเส้นเหมือนภาษาส่วนใหญ่ มันเป็นตาราง 2d ของคำแนะนำตัวอักษรเดียวซึ่งการควบคุมสามารถไหลไปในทิศทางใดก็ได้

>      v
^      <

ตัวละครเหล่านี้เปลี่ยนทิศทางของการควบคุมเมื่อถูกโจมตีสิ่งนี้ทำให้เกิดลูปหลัก

 &+~1+

อินพุตนี้ป้อนตัวเลขและดันลงบนสแต็ก ( &) ดึงค่าบนสุดสองสแต็กออกจากสแต็กเพิ่มและดันกลับเข้าไปในสแต็ก ( +) ป้อนอักขระเดียวและวางค่า ascii บนสแต็ก ( ~) จากนั้น เพิ่ม 1 ลงบนสแต็กและเพิ่ม (1+ )

ล่ามที่ฉันใช้คืน -1 สำหรับการสิ้นสุดอินพุตบางคืน 0 แทนเพื่อให้1+สามารถลบส่วนสำหรับพวกเขา

      #v_.@

#สาเหตุที่ทำให้ตัวละครต่อไปที่จะถูกข้ามไปแล้ว_ปรากฏค่าออกมาจาก stack และถ้ามันเป็นศูนย์ส่งควบคุมที่เหมาะสมมิฉะนั้นจะส่งไปทางซ้าย ถ้าค่าเป็นศูนย์.ปรากฏขึ้นค่าปิดสแต็กและส่งออกเป็นจำนวนเต็มและ@หยุดโปรแกรม มิฉะนั้นvส่งการควบคุมลงไปที่ห่วงกลับ

^*4*8*8<

สิ่งนี้จะคูณค่าสูงสุดของสแต็กด้วย 256 และส่งคืนการควบคุมไปยังจุดเริ่มต้น


ให้อภัยความไม่รู้ของฉัน แต่ควรจะเป็น 19 ตัวอักษร? ฉันเข้าใจว่าทำไมคุณถึงพูดว่า 2x11 แต่ทำไมมันถึงเป็นเช่นนั้น
Kyle Rozendo

Befungeเป็นภาษา 2d หากคุณมองหา>v<^ว่านั่นคือลูปหลักในโปรแกรมนี้ ฉันเดาว่าในกรณีนี้การควบคุมไม่ได้ผ่านช่องว่าง 3 อันสุดท้ายที่อยู่ด้านล่าง แต่ฉันคิดว่ามันง่ายที่สุดที่จะนับโปรแกรม Befunge เป็นสี่เหลี่ยมผืนผ้าที่เล็กที่สุด และถ้าคุณต้องลองและนับลำดับการควบคุมคุณจะมีปัญหากับโปรแกรมปรับเปลี่ยนตนเอง
Nemo157

5

ทับทิม (40)

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

->

q["192.168.1.1"]
=> 3232235777

แนวคิดที่ดีในการใช้ regexp
Hauleth

ฉลาดมาก! นอกจากนี้คุณสามารถเขียนto_i 16เป็นhexบันทึกตัวละครบางตัว
Paul Prestidge

ขอบคุณ @ ประสานที่ทำให้ทั้งสองอย่างนี้และเชื่อมโยงตัวละครสั้นกว่า 4 ตัว
jsvnm


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: การใช้บูสต์ช่วยเพิ่มจำนวนตัวอักษรลงไปไหม? :)
กิระ

3

PowerShell 66 61

ความหลากหลายของคำตอบของ Joey:

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' จะมี 47 ตัวอักษรใน AWK (ไม่ใช่โบกี้กอล์ฟ แต่มันอยู่ในหลุม)

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}ในกรณีของคุณคุณจะนับเฉพาะ แน่นอนว่าคุณต้องย้ายตัวแยกฟิลด์ไปไว้ในโปรแกรมแทนที่จะระบุเป็นแฟล็ก
Jonah

3

Bash - 46

สารบัญ

คุณจะพบ 4 รุ่นที่แตกต่างกัน golfed:

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หลังจากหรือครั้งสุดท้าย |และ
  • ที่ตั้งไว้_ไป32 จะอ่านสร้างจากซ้ายไปขวาเพื่อ$((_-=8))ให้24ที่ 1 กะ , 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ถ้าสตริง 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

อีกรุ่นที่แตกต่าง golfed: 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...ที่สุด

golfed ด้วย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

@Jonah: set -- foo barจะเติม$@กับfooเป็น$1และบาร์$2เป็น
F. Hauri

@Jonah เพิ่มเวอร์ชั่นใหม่แล้ว
F. Hauri

ขอบคุณสำหรับคำอธิบาย
Jonah

เวอร์ชั่นใหม่! golfed เพิ่มเติม -1 ถ่าน !!
F. Hauri

2

Windows PowerShell, 70

วิธีการของNaïve:

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

ด้วยการใช้ System.Net.IP ที่อยู่: 76

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

ทดสอบ:

> '192.168.1.1'|I
3232235777


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/\./
คนขี้ขลาดนิรนาม

ด้วยรุ่นฟังก์ชั่นใช่ แต่รุ่นอินไลน์ไม่ได้เพราะคุณจำเป็นsplit q{.}ต้องหลีกเลี่ยงคำพูดของเชลล์: /
Kent Fredric

2

Haskell - 14 ตัวอักษร

(.) a=(256*a+)

การใช้งานใน GHCi:

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

ปัญหาเดียวคือคุณต้องใส่ช่องว่างทางซ้ายหรือขวาของจุดมิฉะนั้นตัวเลขจะถูกตีความว่าเป็นจุดลอยตัว


ใจที่จะเพิ่มคำอธิบายสั้น ๆ ?
Jonah

ตัวดำเนินการ dot infix ได้รับการนิยามใหม่ให้ทำการคำนวณอย่างชาญฉลาดมาก ๆ !
บันทึก

นี่ฉลาดมาก แต่ไม่ได้ใช้รูปแบบอินพุตที่ถูกต้อง (เพราะช่องว่าง)
12Me21


2

JavaScript (45 ตัวอักษร)

ต้องการการสนับสนุนสำหรับ.reduce()วิธีการที่นำมาใช้ในอาร์เรย์ ES5 และลูกศรฟังก์ชั่น

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

@Nellius - ค่อนข้างถูกต้อง ฉันไม่ได้คิดถึงการตรวจสอบที่ตรวจสอบโดยทั่วไปเกี่ยวกับการรวบรวม ขอบคุณจะแก้ไขทันที
Kyle Rozendo

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 ให้อภัยฉันถ้าช่องว่างไวเหมือนงูหลาม แต่มันดูไม่ออกกอล์ฟ คุณสามารถลบตัวแบ่งบรรทัดสองครั้งหรือตัวแบ่งบรรทัดระหว่างคำสั่งที่ปิดท้ายเครื่องหมายอัฒภาค
Jonah


1

PHP (ไม่มี builtins / eval) - 54

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

สิ่งนี้ไม่ควรเปิดด้วย<?phpไม่ใช่<หรือ?
TRiG

@TRiG ฉันเชื่อว่าคุณสามารถเปลี่ยนตัวคั่นการเปิด PHP ในไฟล์ปรับแต่ง มีประโยชน์ในกรณีนี้
Xeoncross

@Xeoncross อา. เรียบร้อย ฉันอาจลองสักวันหนึ่งเพื่อยุ่งกับหัวเพื่อนร่วมงานของฉัน
TRiG

1

Perl, 14 ตัวอักษร:

sub _{unpack'L>',pop}

# Example usage
print _(10.10.104.36) # prints 168454180

5
คุณสร้างตัวละคร 14 ตัวนี้ได้อย่างไร ฉันนับ 21.
Peter Taylor




โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.