Целочисленная функция преобразования 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
Я думаю, что было бы лучше, если бы существовало ограничение, запрещающее встроенные функции языка.
Натан Осман
@ Джордж - Да, это было бы, но люди уже сделали это прежде, чем я мог вставить это - я честно не думал об этом.
Кайл Розендо

Ответы:

8

Рубин (без встроенных / eval) - 47

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

Тестовое задание:

s["192.168.1.1"]
3232235777
Арно Ле Блан
источник
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на самом деле избыточно :)

Nim
источник
очень умное использование main () :) .. моя версия была 116 байтов.
Акира
Я получаю ошибку сегментации.
Натан Осман
@ Джордж, каков твой вклад и как ты это делаешь?
Ним
Я запускаю его с помощью своего пользовательского скрипта
Натан Осман,
Это не будет работать в C ++, вы не можете вызывать main рекурсивно.
Скотт Логан
7

Golfscript - 16 символов

{[~]2%256base}:f

Как отдельная программа, это еще короче в 11.

~]2%256base

Чрезвычайно просто. Оценивает входную строку ( ~) и помещает ее в массив []. Поскольку .s в строке дублируют верхнюю часть стека, мы принимаем только все остальные члены в array ( 2%). Теперь у нас есть массив, который в основном представляет собой базовое число 256, поэтому мы используем встроенную функцию для выполнения преобразования. ( 256base).

Nabb
источник
очень умно. я думаю, base256 трактуется по-разному, скажем base10 или base16, тогда где 48 => 0?
gnibbler
@gnibbler: Я не уверен, что вы предлагаете - функция base обрабатывает все базы одинаково, например {:B;{\B*+}*}:base(хотя реальная функция перегружена для преобразования другим способом). Интересно отметить, что базовое преобразование для строк такое же, как для массивов (поскольку строки - это просто массивы без вложенности, но с другим форматом вывода).
Набб
да, я думал о базовых преобразованиях строк, поэтому я не достаточно внимательно посмотрел на baseмой ответ
gnibbler
Очень умно. Теперь сделайте это для адреса IPv6. :)
Ильмари Каронен
6

Befunge - 2x11 = 22 символа

Так близко, Befunge выиграет один день.

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

объяснение

Самая большая отличительная черта Befunge состоит в том, что вместо линейного набора инструкций, как большинство языков; это двумерная сетка односимвольных инструкций, где управление может проходить в любом направлении.

>      v
^      <

Эти персонажи меняют направление управления при попадании, это делает основной цикл.

 &+~1+

Это вводит число и помещает его в стек ( &), выталкивает два верхних значения из стека, добавляет их и помещает обратно в стек (+ и помещает ), вводит один символ и помещает его значение ascii в стек ( ~), затем помещает 1 в стек и добавляет их ( 1+).

Интерпретатор, который я использовал, возвращает -1 для конца ввода, некоторые возвращают 0 вместо этого, чтобы 1+часть могла быть удалена для них.

      #v_.@

#Вызывает следующий символ , который будет пропущен, то _щелчки значение из стека , и если он равен нулю посылает управляющий вправе, в противном случае посылает его влево. Если значение было равно нулю, оно .выталкивает значение из стека и выводит его как целое число и @останавливает программу. В противном случае vотправляет управление обратно в цикл возврата.

^*4*8*8<

Это просто умножает верхнее значение стека на 256 и возвращает управление к началу.

Nemo157
источник
Прошу прощения за мое невежество, но должно ли это быть 19 символов? Я понимаю, почему вы говорите 2x11, но почему это так работает?
Кайл Розендо
Befunge - это двумерный язык, если вы ищете тот, >v<^который на самом деле является основным циклом в этой программе. Я предполагаю, что в этом случае элемент управления фактически не проходит через эти последние 3 пробела внизу, но я считаю, что проще всего просто считать программы Befunge как наименьший ограничивающий прямоугольник; и если вы попытаетесь посчитать поток управления, у вас возникнут проблемы с самоизменяющимися программами.
Nemo157
5

Рубин (40)

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

->

q["192.168.1.1"]
=> 3232235777
jsvnm
источник
Хорошая идея использования регулярных выражений.
Хаулет
Очень умно! Также вы можете написать to_i 16как hexсохранить некоторые символы.
Пол Престиж
спасибо @chron, который сделал это и ссылку на 4 символа короче
jsvnm
4

Рубин - 46 символов

require"ipaddr"
def f s;IPAddr.new(s).to_i;end
gnibbler
источник
Я думаю, что это обман. ;-)
Крис Шестер-Янг
3

Golfscript - 21 символ

{'.'/{~}%{\256*+}*}:f
gnibbler
источник
+1 Хороший твердый раствор. Разве вы не хотите, чтобы GolfScript предоставлял операторы сдвига битов? ;-) (Хотя, черт возьми, я знаю, к каким символам они должны быть привязаны.)
Крис Джестер-Янг
3

Python 56 45

c=lambda x:eval('((('+x.replace('.','<<8)+'))
Александр
источник
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;
}
grokus
источник
@ Джордж Эдисон: использование надстройки помогает сократить количество символов? :)
Акира
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

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

Баш (версия 4.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 Добавлена ​​новая версия
Ф. Хаури
Спасибо за объяснение.
Иона
Новая версия! больше гольфа, -1 символ !!
Ф. Хаури
2

Windows PowerShell, 70

Наивный подход:

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

С использованием System.Net.IPAddress: 76

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

Тестовое задание:

> '192.168.1.1'|I
3232235777
детеныш
источник
2

Befunge-93 - 36 персонажей

&"~"2+::8****&884**:**&884***&++++.@
MiffTheFox
источник
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{.}бы обойти необходимость избегать кавычек оболочки: /
Кент Фредрик
2

Haskell - 14 символов

(.) a=(256*a+)

Использование в GHCi:

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

Единственная проблема заключается в том, что вы должны ставить пробелы слева или справа от точки, в противном случае числа будут интерпретироваться как числа с плавающей запятой.

Фомино воскресенье
источник
возражаете добавить краткое объяснение?
Иона
Оператор dot infix переопределен для выполнения вычислений, действительно очень умный!
памятка
Это очень умно, но он не использует правильный формат ввода (из-за пробелов)
12Me21
2

C # - 77 символов

Func<string,uint>F=s=>s.Split('.').Aggregate(0u,(c,b)=>(c<<8)+uint.Parse(b));
Mormegil
источник
2

JavaScript (45 символов)

Требуется поддержка .reduce()метода Array, представленного в ES5, и функций стрелок .

f=(x)=>x.split('.').reduce((p,c)=>p<<8|c)>>>0
PleaseStand
источник
Хм ... я не знал, что >>> работал так (преобразование в 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
Mazzy
источник
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 полных байта.
Неллиус
@ Неллиус - совершенно верно. Я даже не думал проверять это, в основном проверял при компиляции. Спасибо, сейчас исправлю.
Кайл Розендо
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, так что прости меня, если он чувствителен к пробелам, как питон, но это не похоже на игру в гольф. Можете ли вы удалить двойные разрывы строк или разрывы строк между операторами с точкой с запятой?
Иона
1

Python 3,2 (69)

sum((int(j)*4**(4*i)) for i,j in enumerate(input().split('.')[::-1]))
l0nwlf
источник
1

PHP (без встроенных / 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
Grimmy
источник
5
Как вы делаете это 14 символов? Я считаю 21.
Питер Тейлор
1

C (gcc) -m32 / POSIX, 33 байта

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

Попробуйте онлайн!

На большой обратный порядок байт платформы, вы могли бы просто определить макрос -Df=inet_atonдля 13 байт .

nwellnhof
источник