Функція перетворення цілого числа 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.