Целочисленная функция преобразования 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на самом деле избыточно :)


очень умное использование main () :) .. моя версия была 116 байтов.
Акира

Я получаю ошибку сегментации.
Натан Осман

@ Джордж, каков твой вклад и как ты это делаешь?
Ним

Я запускаю его с помощью своего пользовательского скрипта
Натан Осман,

Это не будет работать в C ++, вы не можете вызывать main рекурсивно.
Скотт Логан

7

Golfscript - 16 символов

{[~]2%256base}:f

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

~]2%256base

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


очень умно. я думаю, 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 и возвращает управление к началу.


Прошу прощения за мое невежество, но должно ли это быть 19 символов? Я понимаю, почему вы говорите 2x11, но почему это так работает?
Кайл Розендо

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

5

Рубин (40)

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

->

q["192.168.1.1"]
=> 3232235777

Хорошая идея использования регулярных выражений.
Хаулет

Очень умно! Также вы можете написать to_i 16как hexсохранить некоторые символы.
Пол Престиж

спасибо @chron, который сделал это и ссылку на 4 символа короче
jsvnm


3

Golfscript - 21 символ

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

+1 Хороший твердый раствор. Разве вы не хотите, чтобы GolfScript предоставлял операторы сдвига битов? ;-) (Хотя, черт возьми, я знаю, к каким символам они должны быть привязаны.)
Крис Джестер-Янг


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

@ Джордж Эдисон: использование надстройки помогает сократить количество символов? :)
Акира

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

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

2

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

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

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

Хм ... я не знал, что >>> работал так (преобразование в 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

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

PHP (без встроенных / eval) - 54

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

Разве это не должно открыться <?php, не только <?
TRiG

@ TRiG, ​​я считаю, что вы можете изменить разделитель открытия PHP в файле конфигурации. Полезно в этом случае.
Xeoncross

@Xeoncross. Ах. Ухоженная. Я мог бы попробовать это однажды, просто чтобы поиграть с головами моих коллег.
TRiG





Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.