Функція перетворення цілого числа 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 - Так, було б, але люди вже робили це до того, як я міг би це вкласти - я, чесно кажучи, не думав про це.
Кайл Розендо

Відповіді:





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

EDIT: видалено C ++, не збирається без заголовків; з GCC, theprintfstrtol виклики та функції викликають вбудовані функції, отже, заголовки можна пропускати. Спасибі на @ugoren за порадами. Це складеться так, як без додаткових варіантів gcc.

EDIT2: returnнасправді зайве :)


дуже розумне використання main () :) .. моєї версії було 116 байт.
акіра

Я отримую помилку в сегментації.
Натан Осман

@George, який ваш внесок і як ви його працюєте?
Нім

Я запускаю його з моїм UserScript через codepad.org
Натан Осман,

Це не працюватиме на C ++, ви не можете зателефонувати основним рекурсивно.
Скотт Логан

7

Гольфскрипт - 16 символів

{[~]2%256base}:f

Як самостійна програма, це ще коротше на 11.

~]2%256base

Надзвичайно прямолінійний. Оцінює вхідний рядок ( ~) і вводить його в масив []. Оскільки .s у рядку дублюють верхню частину стека, ми беремо лише кожен інший додаток у масиві ( 2%). Тепер у нас є масив, який в основному представляє базове число 256, тому для перетворення використовуємо вбудовану функцію. ( 256base).


дуже розумний. я думаю, що base256 трактується по-різному, щоб сказати base10 або base16, то де 48 => 0?
гніблер

@ gnibbler: Я не впевнений, що ви пропонуєте - базова функція обробляє всі бази однаково, наприклад {:B;{\B*+}*}:base(хоча реальна функція перевантажена для перетворень в інший спосіб). Цікаво відзначити, що базове перетворення рядків таке ж, як і масиви (оскільки рядки - це просто масиви без вкладення, але з іншим вихідним форматом).
Nabb

так, я думав про базові перетворення рядків, тому я не придивився досить уважно baseдо своєї відповіді
gnibbler

Дуже розумний. Тепер зробіть це для адреси IPv6. :)
Ільмарі Каронен

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 - це двозначна мова, якщо ви шукаєте те, >v<^що є насправді основним циклом у цій програмі. Я думаю, що в цьому випадку контроль насправді не проходить через останні три пробіли в нижній частині, але мені здається, що найпростіше просто вважати програми Befunge як найменший обмежуючий прямокутник; і якщо ви хочете спробувати підрахувати потік управління, ви потрапляєте в проблеми з програмами, що змінюють себе.
Nemo157

5

Рубін (40)

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

->

q["192.168.1.1"]
=> 3232235777

Хороша ідея використання regexp.
Hauleth

Дуже розумний! Також ви можете написати, to_i 16як hexзберегти деякі символи.
Пол Престиждж

дякую @chron, що зробило це і тим, що посилання на 4 символи коротше
jsvnm


3

Гольфскрипт - 21 знак

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

+1 Хороший твердий розчин. Ви не хочете, щоб GolfScript надав оператори з переміщенням бітів? ;-) (Хоча, проклятий, якщо я знаю, до яких символів вони повинні бути прив’язані.)
Кріс 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

Аргу, я, мабуть, був дурним, що пропустив це ...
Джої,

3

AWK в ~ 47 символів

Тут першокласник ... Гм, не впевнений, як це порахувати, але без "відлуння" це 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}. Звичайно, вам доведеться перемістити роздільник поля в програму, а не вказувати його як прапор.
Йона

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після останнього АБО | і
  • встановлено _на 32 . буде читати конструкцію зліва направо, тому $((_-=8))зробіть 24в 1-й зміні , 16на другій і так далі.

в дії:

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

Для розваги: ​​спроба отримати $_контент після цього:

echo $_
3232235777

; -б

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
}

Ви можете додати коротке пояснення? Я намагався потрапити в гольф з баш, і я не стежу за тим, що відбувається з set --частиною. Спасибі.
Йона

@Jonah: set -- foo barзаповнить $@з взувши як $1і бар , як $2.
Ф. Хаурі

@Jonah Додано нову версію
F. Hauri

Дякую за пояснення.
Йона

Нова версія! більше гольфу, -1 чар !!
Ф. Хаурі

2

Windows PowerShell, 70

Наївний підхід:

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 ( for oneliners. )(40)

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

# Use value in $i

DIY Function(65):

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

You can split by a string, so you save a character by using split'.' rather than split/\./
anonymous coward

With the function version, yes, but the inline version no, because you'd need split q{.} to get around the need to escape shell quotes :/
Kent Fredric

2

Haskell - 14 chars

(.) a=(256*a+)

usage in GHCi:

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

The only problem is that you have to put spaces left or right of the dot, otherwise the numbers will be interpreted as floating point.


mind adding a brief explanation?
Jonah

the dot infix operator is redefined to do the computation, very smart indeed!
memo

This is very clever, but it doesn't use the correct input format (because of the spaces)
12Me21

2

C# – 77 chars

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

2

JavaScript (45 characters)

Requires support for the .reduce() Array method introduced in ES5 and arrow functions.

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

Huh... I didn't know >>> worked like that (converting to unsigned 32 bit integer)
12Me21

2

Powershell, 47 43 bytes

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

Test script:

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

Output:

True: 3232235777
True: 168454180
True: 134744072


1

C# - 120 Characters

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

My first code golf - be gentle ;)


You can remove the spaces around your first '='. However, your main problem is int overflow ;). Remember, an IP address takes up 4 full bytes.
Nellius

@Nellius - quite right. I didn't even think of checking that, basically checked on compile. Thanks, will fix now.
Kyle Rozendo

1

D: 84 Characters

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

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

    return n;
}

i don't know D so forgive me if it's whitespace sensitive like python, but this doesn't look golfed. can you remove the double line breaks or the line breaks between semi-colon terminated statements?
Jonah

1

Python 3.2 (69)

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

1

PHP (no builtins/eval) - 54

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

Shouldn't this open with <?php, not just <?
TRiG

@TRiG, I believe you can change the PHP opening delimiter in the config file. Useful in this case.
Xeoncross

@Xeoncross. Ah. Neat. I might try that one day, just to mess with my workmates' heads.
TRiG

1

Perl, 14 characters:

sub _{unpack'L>',pop}

# Example usage
print _(10.10.104.36) # prints 168454180

5
How do you make that 14 characters? I count 21.
Peter Taylor



Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.