Fungsi Konversi Integer IPv4

17

Tulis fungsi terpendek untuk mengubah alamat IP menjadi representasi integernya dan output sebagai integer.

Untuk mengubah alamat IPv4 ke representasi integernya, perhitungan berikut diperlukan:

  • Pisahkan alamat IP menjadi empat oktet.
  • (Octet1 * 16777216) + (Octet2 * 65536) + (Octet3 * 256) + (Octet4)

Input Sampel

192.168.1.1           10.10.104.36           8.8.8.8

Output Sampel

3232235777            168454180              134744072
Kyle Rozendo
sumber
2
Saya pikir ini akan lebih baik jika ada pembatasan di tempat yang melarang fungsi bawaan bahasa.
Nathan Osman
@ George - Ya, itu akan terjadi, tetapi orang-orang sudah melakukannya sebelum saya bisa memasukkannya ke dalam - saya sejujurnya tidak memikirkannya.
Kyle Rozendo

Jawaban:

11

PHP - 21 Karakter

<?=ip2long($argv[1]);
ircmaxell
sumber
8

MySQL - 20 Karakter

SELECT INET_ATON(s);
ircmaxell
sumber
8

Ruby (tanpa builtin / eval) - 47

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

Uji:

s["192.168.1.1"]
3232235777
Arnaud Le Blanc
sumber
8

C: 79 karakter

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

EDIT: dihapus C ++, tidak akan dikompilasi tanpa header; dengan GCC, theprintf dan strtolpemanggilan fungsi memicu fungsi bawaan, karenanya tajuk dapat dilewati. Terima kasih kepada @ugoren untuk tipsnya. Ini akan dikompilasi apa adanya tanpa opsi tambahan untuk gcc.

EDIT2: returnsebenarnya berlebihan :)

Nim
sumber
sangat pintar menggunakan main () :) .. versi saya 116bytes.
akira
Saya mendapatkan kesalahan segmentasi.
Nathan Osman
@ George, apa masukan Anda dan bagaimana Anda menjalankannya?
Nim
Saya menjalankannya dengan UserScript saya melalui codepad.org
Nathan Osman
Ini tidak akan berfungsi di C ++, Anda tidak dapat memanggil utama secara rekursif.
Scott Logan
7

Golfscript - 16 karakter

{[~]2%256base}:f

Sebagai program mandiri, ini bahkan lebih pendek yaitu 11.

~]2%256base

Sangat mudah. Mengevaluasi string input ( ~) dan memasukkannya ke dalam array []. Karena .s dalam string menduplikasi bagian atas tumpukan, kami hanya mengambil setiap istilah lain dalam array ( 2%). Kami sekarang memiliki array yang pada dasarnya mewakili angka 256 basis, jadi kami menggunakan fungsi bawaan untuk melakukan konversi. ( 256base).

Nabb
sumber
sangat pintar. Saya kira base256 diperlakukan berbeda untuk mengatakan base10 atau base16 lalu di mana 48 => 0?
gnibbler
@gnibbler: Saya tidak yakin apa yang Anda sarankan - fungsi basis menangani semua basis dengan cara yang sama, misalnya {:B;{\B*+}*}:base(meskipun fungsi sebenarnya kelebihan beban untuk konversi dengan cara lain). Yang menarik untuk dicatat adalah bahwa konversi basis untuk string sama dengan array (karena string hanya array tanpa bersarang, tetapi dengan format output yang berbeda).
Nabb
ya saya sedang memikirkan konversi dasar string, jadi saya tidak melihat cukup dekat baseuntuk jawaban saya
gnibbler
Sangat pintar. Sekarang lakukan itu untuk alamat IPv6. :)
Ilmari Karonen
6

Befunge - 2x11 = 22 karakter

Begitu dekat, Befunge akan menang suatu hari.

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

Penjelasan

Fitur pembeda terbesar dari Befunge adalah bahwa alih-alih menjadi seperangkat instruksi linier seperti kebanyakan bahasa; itu adalah kotak 2d instruksi karakter tunggal, di mana kontrol dapat mengalir ke segala arah.

>      v
^      <

Karakter-karakter ini mengubah arah kontrol ketika mereka dipukul, ini membuat loop utama.

 &+~1+

Ini memasukkan angka dan mendorongnya ke tumpukan ( &), mengeluarkan dua nilai teratas dari tumpukan, menambahkannya dan mendorongnya kembali ke tumpukan ( +), memasukkan satu karakter dan menempatkan nilai ascii pada tumpukan ( ~), lalu mendorong 1 ke tumpukan dan menambahkannya ( 1+).

Penerjemah yang saya gunakan mengembalikan -1 untuk akhir input, beberapa mengembalikan 0 sehingga 1+bagian dapat dihapus untuk mereka.

      #v_.@

The #menyebabkan karakter berikutnya akan dilewati, maka _muncul nilai dari tumpukan dan jika itu adalah nol mengirimkan kontrol yang tepat, jika tidak mengirimkannya kiri. Jika nilainya nol .muncul nilai dari stack dan output sebagai integer dan @menghentikan program. Kalau tidak, vkirim kontrol ke loop kembali.

^*4*8*8<

Ini hanya mengalikan nilai teratas tumpukan dengan 256 dan mengembalikan kontrol ke awal.

Nemo157
sumber
Maafkan ketidaktahuan saya, tetapi haruskah itu 19 karakter? Saya mengerti mengapa Anda mengatakan 2x11, tetapi mengapa bisa seperti itu?
Kyle Rozendo
Befunge adalah bahasa 2d, jika Anda mencari >v<^yang sebenarnya adalah loop utama dalam program ini. Saya kira dalam hal ini kontrol tidak benar-benar melewati 3 ruang terakhir di bagian bawah, tapi saya merasa lebih mudah untuk hanya menghitung program Befunge sebagai persegi panjang terikat terkecil; dan jika Anda mencoba dan menghitung aliran kontrol Anda mendapat masalah dengan program modifikasi diri.
Nemo157
5

Ruby (40)

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

->

q["192.168.1.1"]
=> 3232235777
jsvnm
sumber
Ide bagus menggunakan regexp.
Hauleth
Sangat pintar! Anda juga dapat menulis to_i 16sebagai hexuntuk menyimpan beberapa karakter.
Paul Prestidge
terima kasih @ sink yang membuat ini dan tautkan 4 karakter lebih pendek
jsvnm
4

Ruby - 46 karakter

require"ipaddr"
def f s;IPAddr.new(s).to_i;end
gnibbler
sumber
Saya pikir itu merupakan kecurangan. ;-)
Chris Jester-Young
3

Golfscript - 21 karakter

{'.'/{~}%{\256*+}*}:f
gnibbler
sumber
+1 Solusi solid yang bagus. Apakah Anda tidak ingin GolfScript menyediakan operator bit-shifting? ;-) (Padahal, terkutuk jika saya tahu simbol mana yang harus mereka terikat.)
Chris Jester-Young
3

Python 56 45

c=lambda x:eval('((('+x.replace('.','<<8)+'))
Alexandru
sumber
3

C ++ - banyak karakter

#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;
}
grokus
sumber
@ George Edison: menggunakan boost membantu menurunkan jumlah karakter? :)
akira
3

PowerShell 66 61

Variasi jawaban 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
Ty Auvil
sumber
Argh, aku pasti bodoh karena melewatkan itu ...
Joey
3

AWK dalam ~ 47 karakter

Timer pertama di sini ... Um, tidak yakin bagaimana cara menghitung ini, tetapi tanpa 'gema' itu 47 karakter di AWK. (Bukan golf momok, tapi ada di lubang.)

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

Sehari penuh lebih awal untuk #tbt, jadi saya benar-benar bertemu jadwal !!! * 8-)

Hari spanduk.

Blair Wyman
sumber
1
Selamat datang! Anda hanya akan menghitung isi dari apa yang Anda masukkan ke dalam skrip awk. Lihat jawaban ini . Dalam kasus Anda, Anda hanya akan menghitung {print $1*16777216+$2*65536+$3*256+$4}. Tentu saja Anda harus memindahkan pemisah bidang ke dalam program, daripada menetapkannya sebagai bendera.
Jonah
3

Bash - 46

Daftar Isi

Anda akan menemukan 4 versi golf yang berbeda:

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

Versi baru! 2018-11-15 Lebih banyak bermain golf, 46 karakter

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

Penjelasan

  • Saya menggunakan $_ lebih banyak golf.
  • Sintaksis ${1//./ } akan mengganti setiap titik .dengan spasi .
  • begitu printf akan membuat sesuatu seperti192<<(_-=8)|168<<(_-=8)|1<<(_-=8)|1<<(_-=8)|
  • maka kita akan menambahkan 0setelah terakhir OR | dan
  • diatur _ke 32 . akan membaca konstruk dari kiri ke kanan, jadi $((_-=8))buat 24di shift pertama ,16 kedua, dan seterusnya.

dalam aksi:

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

Untuk bersenang-senang: mencoba untuk mendapatkan $_konten, setelah ini:

echo $_
3232235777

; -b

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

Ok, itu benar 32 - 4 x 8 = 0

Dalam suatu fungsi:

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

atau ke dalam satu lingkaran: -> 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

Pos pertama

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

Penjelasan:

  • Sintaks${1//./ } akan mengganti setiap titik .dengan spasi .
  • set --mengatur parameter posisi ( $@=($1 $2 $3...))
  • Jadi set -- ${1//./ }akan membagi $1oleh titik dan set $1, $2, $3dan $4apakah string containg3 titik (dan tidak ada spasi).

dalam aksi:

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

atau dalam suatu fungsi:

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

atau ke dalam satu lingkaran: -> 61

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

dalam aksi:

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

Versi lain berbeda golf: 65

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

Sampel:

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

Dalam satu lingkaran (+14): 82

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

* atau sedikit lebih jelek: 70 *

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

di mana printfberikan beberapa string seperti |192<<24 |168<<16 |1<<8|1<<24 |0<<16 |0<<8kita harus memotong pada akhirnya<<2... .

bermain golf dengan mapfile, lebih lama: 68

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

atau dengan loop: 82

ip2int() {
    for a;do
      mapfile -td. i<<<$a;for((a=o=0;a<4;o+=i[a]<<(3-a++)*8)){ :;};echo $o
    done
}
F. Hauri
sumber
dapatkah Anda menambahkan penjelasan singkat? Saya sudah mencoba untuk bermain golf bash dan saya tidak mengikuti apa yang terjadi dengan set --bagian itu. Terima kasih.
Jonah
@Jonah: set -- foo barakan diisi $@dengan foo as $1dan bar as $2.
F. Hauri
@Jonah Menambahkan versi baru
F. Hauri
Terima kasih untuk penjelasannya.
Jonah
Versi baru! lebih banyak bermain golf, -1 char !!
F. Hauri
2

Windows PowerShell, 70

Pendekatan naif:

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

Dengan menggunakan System.Net.IPAddress: 76

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

Uji:

> '192.168.1.1'|I
3232235777
Joey
sumber
2

Befunge-93 - 36 karakter

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

Perl: DIY (untuk oneliners.) (40)

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

# Gunakan nilai dalam $ i

Fungsi DIY (65):

sub atoi{my($i,$j)=(0,3);$i+=($_<<($j--*8))for split'.',shift;$i}
Kent Fredric
sumber
Anda dapat memisahkan dengan string, sehingga Anda menyimpan karakter dengan menggunakan split'.'daripadasplit/\./
pengecut anonim
Dengan versi fungsi, ya, tetapi versi inline tidak, karena Anda harus split q{.}menyiasati kebutuhan untuk melepaskan diri dari kutipan shell: /
Kent Fredric
2

Haskell - 14 karakter

(.) a=(256*a+)

penggunaan di GHCi:

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

Satu-satunya masalah adalah Anda harus meletakkan spasi di kiri atau kanan titik, jika tidak angka akan ditafsirkan sebagai titik mengambang.

quasimodo
sumber
keberatan menambahkan penjelasan singkat?
Jonah
operator dot infix didefinisikan ulang untuk melakukan perhitungan, memang sangat pintar!
memo
Ini sangat pintar, tetapi tidak menggunakan format input yang benar (karena spasi)
12Me21
2

C # - 77 karakter

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

JavaScript (45 karakter)

Membutuhkan dukungan untuk .reduce()metode Array yang diperkenalkan dalam fungsi ES5 dan panah .

f=(x)=>x.split('.').reduce((p,c)=>p<<8|c)>>>0
Mohon berdiri
sumber
Huh ... Saya tidak tahu >>> bekerja seperti itu (mengkonversi ke integer 32 bit yang tidak ditandatangani)
12Me21
2

Powershell, 47 43 byte

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

Skrip uji:

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

Keluaran:

True: 3232235777
True: 168454180
True: 134744072
mazzy
sumber
1

C # - 120 Karakter

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

Golf kode pertama saya - lembut;)

Kyle Rozendo
sumber
Anda dapat menghapus spasi di sekitar '=' pertama Anda. Namun, masalah utama Anda adalah int overflow;). Ingat, alamat IP membutuhkan 4 byte penuh.
Nellius
@Nellius - benar sekali. Saya bahkan tidak berpikir untuk memeriksanya, pada dasarnya memeriksa kompilasi. Terima kasih, akan perbaiki sekarang.
Kyle Rozendo
1

D: 84 Karakter

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

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

    return n;
}
Jonathan M Davis
sumber
saya tidak tahu D jadi maafkan saya jika spasi putih sensitif seperti python, tapi ini tidak terlihat seperti golf. dapatkah Anda menghapus jeda baris ganda atau jeda baris antara pernyataan semi-colon terminated?
Jonah
1

Python 3.2 (69)

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

PHP (tanpa builtin / eval) - 54

<foreach(explode(".",$argv[1])as$b)$a=@$a<<8|$b;echo$a;
Arnaud Le Blanc
sumber
Bukankah seharusnya ini terbuka <?php, bukan hanya <?
TRiG
@TRiG, ​​saya yakin Anda dapat mengubah pembatas pembuka PHP di file konfigurasi. Berguna dalam hal ini.
Xeoncross
@ Xeoncross. Ah. Rapi. Saya mungkin mencobanya suatu hari nanti, hanya untuk mengacaukan pikiran rekan kerja saya.
TRiG
1

Perl, 14 karakter:

sub _{unpack'L>',pop}

# Example usage
print _(10.10.104.36) # prints 168454180
Grimmy
sumber
5
Bagaimana Anda membuat 14 karakter itu? Saya menghitung 21.
Peter Taylor
1

C (gcc) -m32 / POSIX, 33 byte

f(a){inet_aton(a,&a);a=ntohl(a);}

Cobalah online!

Pada platform big-endian, Anda bisa mendefinisikan makro dengan -Df=inet_atonuntuk 13 byte .

nwellnhof
sumber