Chức năng chuyển đổi số nguyên IPv4


17

Viết hàm ngắn nhất để chuyển đổi địa chỉ IP thành biểu diễn số nguyên và xuất ra dưới dạng số nguyên.

Để thay đổi địa chỉ IPv4 thành biểu diễn số nguyên, cần phải tính toán sau:

  • Chia địa chỉ IP thành bốn octet.
  • (Octet1 * 16777216) + (Octet2 * 65536) + (Octet3 * 256) + (Octet4)

Đầu vào mẫu

192.168.1.1           10.10.104.36           8.8.8.8

Đầu ra mẫu

3232235777            168454180              134744072

2
Tôi nghĩ rằng điều này sẽ tốt hơn nếu có một hạn chế tại chỗ cấm các chức năng tích hợp sẵn của ngôn ngữ.
Nathan Osman

@George - Phải, đúng là như vậy, nhưng mọi người đã làm điều đó trước khi tôi có thể đưa nó vào - Tôi thực sự không nghĩ về điều đó.
Kyle Rozendo

Câu trả lời:




8

Ruby (không có nội dung / eval) - 47

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

Kiểm tra:

s["192.168.1.1"]
3232235777

8

C: 79 ký tự

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

EDIT: đã xóa C ++, sẽ không biên dịch nếu không có tiêu đề; với GCC, các hàm gọi printfstrtolhàm kích hoạt các hàm dựng sẵn, do đó các tiêu đề có thể bị bỏ qua. Thx đến @ugoren cho lời khuyên. Điều này sẽ biên dịch như là không có tùy chọn bổ sung đểgcc .

EDIT2: returnthực sự là dư thừa :)


sử dụng rất thông minh của main () :) .. phiên bản của tôi là 116byte.
akira

Tôi nhận được một lỗi phân khúc.
Nathan Osman

@George, đầu vào của bạn là gì và bạn đang chạy nó như thế nào?
Nim

Tôi đang chạy nó với UserScript của mình thông qua codepad.org
Nathan Osman

Điều này sẽ không hoạt động trong C ++, bạn không thể gọi chính đệ quy.
Scott Logan

7

Golfscript - 16 ký tự

{[~]2%256base}:f

Là một chương trình độc lập, điều này thậm chí còn ngắn hơn ở mức 11.

~]2%256base

Vô cùng đơn giản. Đánh giá chuỗi đầu vào ( ~) và đặt nó vào một mảng []. Vì .s trong chuỗi nhân đôi đỉnh của ngăn xếp, nên chúng tôi chỉ lấy mọi thuật ngữ khác trong mảng ( 2%). Bây giờ chúng ta có một mảng về cơ bản đại diện cho một số cơ sở 256, vì vậy chúng tôi sử dụng hàm tích hợp để thực hiện chuyển đổi. ( 256base).


rất thông minh. tôi đoán base256 được đối xử khác nhau để nói base10 hoặc base16 thì 48 => 0?
gnibbler

@gnibbler: Tôi không chắc chắn những gì bạn đang đề xuất - hàm cơ sở xử lý tất cả các cơ sở theo cùng một cách, ví dụ {:B;{\B*+}*}:base(mặc dù hàm thực bị quá tải cho chuyển đổi theo cách khác). Điều thú vị cần lưu ý là chuyển đổi cơ sở cho các chuỗi giống như các mảng (vì các chuỗi chỉ là các mảng không có lồng nhau, nhưng với định dạng đầu ra khác nhau).
Nabb

vâng tôi đã nghĩ đến việc chuyển đổi cơ bản của các chuỗi, vì vậy tôi đã không nhìn kỹ vào basecâu trả lời của mình
gnibbler

Rất thông minh. Bây giờ làm điều đó cho một địa chỉ IPv6. :)
Ilmari Karonen

6

Befunge - 2x11 = 22 ký tự

Rất gần, Befunge sẽ giành chiến thắng một ngày.

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

Giải trình

Tính năng phân biệt lớn nhất của Befunge là thay vì là một bộ hướng dẫn tuyến tính như hầu hết các ngôn ngữ; nó là một lưới 2d của các lệnh ký tự đơn, trong đó điều khiển có thể chảy theo bất kỳ hướng nào.

>      v
^      <

Các nhân vật này thay đổi hướng điều khiển khi họ bị đánh, điều này làm cho vòng lặp chính.

 &+~1+

Điều này nhập một số và đẩy nó vào ngăn xếp ( &), bật hai giá trị trên cùng ra khỏi ngăn xếp, thêm chúng và đẩy chúng trở lại vào ngăn xếp ( +), nhập một ký tự đơn và đặt giá trị ascii của nó vào ngăn xếp ( ~), sau đó đẩy 1 lên ngăn xếp và thêm chúng ( 1+).

Trình thông dịch tôi đã sử dụng trả về -1 cho cuối đầu vào, một số trả về 0 thay vào đó để 1+phần có thể được gỡ bỏ cho chúng.

      #v_.@

Các #nguyên nhân vật tiếp theo được bỏ qua, thì _pops một giá trị ra khỏi stack và nếu nó là số không gửi điều khiển bên phải, nếu không gửi nó đi. Nếu giá trị bằng 0 sẽ .bật một giá trị ra khỏi ngăn xếp và xuất ra dưới dạng một số nguyên và @dừng chương trình. Nếu không thì vgửi điều khiển xuống vòng lặp trở lại.

^*4*8*8<

Điều này chỉ đơn giản là nhân giá trị hàng đầu của ngăn xếp lên 256 và trả lại quyền điều khiển khi bắt đầu.


Xin tha thứ cho sự thiếu hiểu biết của tôi, nhưng đó có nên là 19 ký tự không? Tôi hiểu tại sao bạn nói 2x11, nhưng tại sao nó hoạt động theo cách đó?
Kyle Rozendo

Befunge là ngôn ngữ 2d, nếu bạn tìm kiếm >v<^đó thực sự là vòng lặp chính trong chương trình này. Tôi đoán trong trường hợp này điều khiển không thực sự đi qua 3 khoảng trống cuối cùng ở phía dưới, nhưng tôi thấy dễ dàng nhất khi chỉ tính các chương trình Befunge là hình chữ nhật giới hạn nhỏ nhất; và nếu bạn đã cố gắng và đếm dòng điều khiển, bạn sẽ gặp rắc rối với các chương trình tự sửa đổi.
Nemo157

5

Hồng ngọc (40)

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

->

q["192.168.1.1"]
=> 3232235777

Ý tưởng tốt đẹp của việc sử dụng regrec.
Hauleth

Rất thông minh! Ngoài ra, bạn có thể viết to_i 16như hexđể lưu một số ký tự.
Paul Prestidge

cảm ơn @ sync đã làm cho cả hai ký tự này và liên kết 4 ký tự ngắn hơn
jsvnm


3

Golfscript - 21 ký tự

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

+1 Giải pháp vững chắc tốt. Bạn không muốn GolfScript cung cấp các toán tử thay đổi bit? ;-) (Mặc dù, tôi rất ngạc nhiên nếu tôi biết họ nên ràng buộc những biểu tượng nào.)
Chris Jester-Young


3

C ++ - rất nhiều ký tự

#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: sử dụng boost giúp giảm số lượng ký tự? :)
akira

3

PowerShell 66 61

Sự thay đổi về câu trả lời của 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

Argh, tôi đã thật ngu ngốc khi bỏ lỡ điều đó ...
Joey

3

AWK trong ~ 47 ký tự

Hẹn giờ đầu tiên ở đây ... Ừm, không biết làm thế nào để đếm cái này, nhưng không có 'tiếng vang' thì đó là 47 ký tự trong AWK. (Không chính xác là golf bogey, nhưng nó ở trong lỗ.)

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

Cả ngày sớm cho #tbt, vì vậy tôi thực sự đã đáp ứng một lịch trình !!! *số 8-)

Ngày biểu ngữ.


1
Chào mừng bạn Bạn chỉ đếm phần thân của những gì bạn đưa vào một kịch bản awk. Xem câu trả lời này . Trong trường hợp của bạn, bạn chỉ tính {print $1*16777216+$2*65536+$3*256+$4}. Tất nhiên, bạn phải di chuyển dấu tách trường vào chương trình, thay vì chỉ định nó là cờ.
Giô-na

3

Bash - 46

Mục lục

Bạn sẽ tìm thấy 4 phiên bản golf khác nhau:

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

Phiên bản mới! 2018-11-15 Chơi gôn nhiều hơn, 46 char

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

Giải trình

  • Tôi đã sử dụng $_ để chơi golf nhiều hơn.
  • Cú pháp ${1//./ }sẽ thay thế mọi dấu chấm. bằng dấu cách .
  • vì thế printf sẽ làm cho một cái gì đó như192<<(_-=8)|168<<(_-=8)|1<<(_-=8)|1<<(_-=8)|
  • sau đó chúng tôi sẽ thêm 0sau lần cuối HOẶC |
  • đặt trước _đến 32 . sẽ đọc cấu trúc từ trái sang phải, vì vậy $((_-=8))hãy thực hiện 24ca 1 , 16vào giây, v.v.

trong hành động:

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

Để giải trí: cố gắng lấy $_nội dung, sau này:

echo $_
3232235777

; -b

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

Ok, đúng rồi 32 - 4 x 8 = 0

Trong một chức năng:

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

hoặc vào một vòng lặp: -> 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

Bài viết đầu tiên

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

Giải trình:

  • Cú pháp ${1//./ }sẽ thay thế mọi dấu chấm .bằng dấu cách .
  • set --đặt tham số vị trí ( $@=($1 $2 $3...))
  • Vì vậy, set -- ${1//./ }sẽ chia $1bởi dấu chấm và bộ $1, $2, $3$4nếu chuỗi có chứa có 3dấu chấm (và không có khoảng trắng).

trong hành động:

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

hoặc trong một chức năng:

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

hoặc vào một vòng lặp: -> 61

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

trong hành động:

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

Một phiên bản khác được đánh gôn khác: 65

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

Mẫu vật:

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

Trong một vòng lặp (+14): 82

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

* hoặc xấu hơn một chút: 70 *

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

nơi printfđưa ra một số chuỗi như |192<<24 |168<<16 |1<<8|1<<24 |0<<16 |0<<8chúng ta phải cắt cuối cùng <<2....

chơi với mapfile, dài hơn: 68

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

hoặc với vòng lặp: 82

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

bạn có thể thêm một lời giải thích ngắn gọn? Tôi đã cố gắng tham gia chơi golf và tôi không theo dõi những gì đang xảy ra với set --phần này. cảm ơn.
Giô-na

@Jonah: set -- foo barsẽ cư trú $@với foo as$1 bar as$2.
F. Hauri

@Jonah Đã thêm phiên bản mới
F. Hauri

Cảm ơn đã giải thích.
Giô-na

Phiên bản mới! chơi gôn nhiều hơn, -1 char !!
F. Hauri

2

Windows PowerShell, 70

Cách tiếp cận ngây thơ:

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

Với việc sử dụng System.Net.IPAddress: 76

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

Kiểm tra:

> '192.168.1.1'|I
3232235777


2

Perl: DIY (đối với oneliners.) (40)

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

# Sử dụng giá trị bằng $ i

Chức năng DIY (65):

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

Bạn có thể chia theo một chuỗi, vì vậy bạn lưu một ký tự bằng cách sử dụng split'.'chứ không phảisplit/\./
kẻ hèn nhát ẩn danh

Với phiên bản chức năng, có, nhưng phiên bản nội tuyến thì không, bởi vì bạn cần phải split q{.}giải quyết nhu cầu thoát dấu ngoặc kép: /
Kent Fredric

2

Haskell - 14 ký tự

(.) a=(256*a+)

sử dụng trong GHCi:

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

Vấn đề duy nhất là bạn phải đặt dấu cách sang trái hoặc phải của dấu chấm, nếu không các số sẽ được hiểu là dấu phẩy động.


tâm trí thêm một lời giải thích ngắn gọn?
Giô-na

toán tử dot infix được xác định lại để thực hiện tính toán, thực sự rất thông minh!
ghi nhớ

Điều này rất thông minh, nhưng nó không sử dụng định dạng đầu vào chính xác (vì khoảng trắng)
12Me21

2

C # - 77 ký tự

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

2

JavaScript (45 ký tự)

Yêu cầu hỗ trợ cho .reduce()phương thức Array được giới thiệu trong các hàm ES5 và mũi tên .

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

Hả ... tôi không biết >>> đã làm việc như vậy (chuyển đổi sang số nguyên 32 bit không dấu)
12Me21

2

Powershell, 47 43 byte

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

Kịch bản thử nghiệm:

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

Đầu ra:

True: 3232235777
True: 168454180
True: 134744072

1

C # - 120 ký tự

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 mã đầu tiên của tôi - hãy nhẹ nhàng;)


Bạn có thể xóa các khoảng trắng xung quanh '=' đầu tiên của bạn. Tuy nhiên, vấn đề chính của bạn là int tràn;). Hãy nhớ rằng, một địa chỉ IP chiếm 4 byte đầy đủ.
Nellius

@Nellius - hoàn toàn đúng. Tôi thậm chí không nghĩ đến việc kiểm tra điều đó, về cơ bản đã kiểm tra biên dịch. Cảm ơn, sẽ sửa chữa ngay.
Kyle Rozendo

1

D: 84 ký tự

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

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

    return n;
}

Tôi không biết D nên tha thứ cho tôi nếu nó nhạy cảm với không gian như trăn, nhưng điều này không giống như chơi gôn. bạn có thể loại bỏ các ngắt dòng kép hoặc ngắt dòng giữa các câu lệnh chấm dứt dấu chấm phẩy không?
Giô-na

1

Con trăn 3.2 (69)

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

1

PHP (không có nội dung / eval) - 54

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

Không nên mở với <?php, không chỉ <?
TRiG

@TRiG, ​​tôi tin rằng bạn có thể thay đổi dấu phân cách mở PHP trong tệp cấu hình. Hữu ích trong trường hợp này.
Xeoncross

@Xeoncross. Ah. Khéo léo. Tôi có thể thử một ngày nào đó, chỉ để gây rối với đầu của đồng nghiệp.
TRiG

1

Perl, 14 ký tự:

sub _{unpack'L>',pop}

# Example usage
print _(10.10.104.36) # prints 168454180

5
Làm thế nào để bạn thực hiện 14 ký tự đó? Tôi đếm 21.
Peter Taylor




Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.