Função de conversão de números inteiros IPv4

17

Escreva a função mais curta para converter um endereço IP em sua representação inteira e faça a saída como um inteiro.

Para alterar um endereço IPv4 para sua representação inteira, é necessário o seguinte cálculo:

  • Divida o endereço IP em quatro octetos.
  • (Octet1 * 16777216) + (Octet2 * 65536) + (Octet3 * 256) + (Octet4)

Entrada de amostra

192.168.1.1           10.10.104.36           8.8.8.8

Saída de amostra

3232235777            168454180              134744072
Kyle Rozendo
fonte
2
Eu acho que isso seria melhor se houvesse uma restrição proibindo as funções internas de uma linguagem.
Nathan Osman
@ George - Sim, teria sido, mas as pessoas já haviam feito isso antes que eu pudesse colocar isso - eu sinceramente não pensei nisso.
Kyle Rozendo

Respostas:

11

PHP - 21 caracteres

<?=ip2long($argv[1]);
ircmaxell
fonte
8

MySQL - 20 caracteres

SELECT INET_ATON(s);
ircmaxell
fonte
8

Ruby (sem builtins / eval) - 47

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

Teste:

s["192.168.1.1"]
3232235777
Arnaud Le Blanc
fonte
8

C: 79 caracteres

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

EDIT: C ++ removido, não seria compilado sem cabeçalhos; com o GCC, as chamadas de função printfe strtolacionam funções internas; portanto, os cabeçalhos podem ser ignorados. Obrigado a @ugoren pelas dicas. Isso irá compilar como está sem opções adicionais para gcc.

EDIT2: returné realmente redundante :)

Nim
fonte
uso muito inteligente de main () :) .. minha versão era 116bytes.
Akira
Eu recebo uma falha de segmentação.
Nathan Osman
@ George, qual é a sua opinião e como está sendo executada?
Nim
Estou correndo com o meu UserScript através codepad.org
Nathan Osman
Isso não funcionará em C ++, você não pode chamar principal recursivamente.
Scott Logan
7

Golfscript - 16 caracteres

{[~]2%256base}:f

Como um programa independente, isso é ainda mais curto aos 11 anos.

~]2%256base

Extremamente direto. Avalia a string de entrada ( ~) e a coloca em uma matriz []. Como os .s na sequência duplicam a parte superior da pilha, usamos apenas todos os outros termos na matriz ( 2%). Agora temos uma matriz que basicamente representa um número 256 básico, então usamos uma função interna para fazer a conversão. ( 256base)

Nabb
fonte
muito esperto. Eu acho que base256 é tratado de forma diferente para dizer base10 ou base16, então onde 48 => 0?
Gnibbler
@gnibbler: Não sei ao certo o que você está sugerindo - a função base lida com todas as bases da mesma maneira, por exemplo {:B;{\B*+}*}:base(embora a função real esteja sobrecarregada para conversões da outra maneira). Interessante notar é que a conversão base para seqüências de caracteres é a mesma que matrizes (como strings são apenas matrizes sem aninhamento, mas com um formato de saída diferente).
Nabb 06/02
Sim, eu estava pensando em conversões de base de cordas, então eu não olhar de perto o suficiente para basea minha resposta
gnibbler
Muito esperto. Agora faça isso para um endereço IPv6. :)
Ilmari Karonen
6

Befunge - 2x11 = 22 caracteres

Tão perto, Befunge vai ganhar um dia.

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

Explicação

A maior característica distintiva do Befunge é que, em vez de ser um conjunto linear de instruções, como a maioria dos idiomas; é uma grade 2D de instruções de caracteres únicos, onde o controle pode fluir em qualquer direção.

>      v
^      <

Esses caracteres mudam a direção do controle quando são atingidos, isso faz o loop principal.

 &+~1+

Isso insere um número e o empurra para a pilha ( &), retira os dois principais valores da pilha, os adiciona e os empurra de volta para a pilha ( +), insere um único caractere e coloca seu valor ascii na pilha ( ~); coloca 1 na pilha e os adiciona ( 1+).

O intérprete que eu estou usando retorna -1 para o final da entrada, alguns retornam 0 para que a 1+parte possa ser removida.

      #v_.@

O #faz com que o próximo caractere a ser ignorado, então os _pops um valor fora da pilha e se ele é zero envia controle direita, caso contrário, envia-o para a esquerda. Se o valor for zero, .um valor é retirado da pilha e o gera como um número inteiro e @para o programa. Caso contrário, venvia o controle para o loop de retorno.

^*4*8*8<

Isso simplesmente multiplica o valor superior da pilha por 256 e retorna o controle ao início.

Nemo157
fonte
Perdoe minha ignorância, mas isso deveria ser 19 caracteres? Entendo por que você diz 2x11, mas por que funciona dessa maneira?
Kyle Rozendo 04/02
O Befunge é uma linguagem 2D, se você procurar o >v<^que é realmente o loop principal neste programa. Acho que, nesse caso, o controle não passa pelos três últimos espaços na parte inferior, mas acho mais fácil contar os programas Befunge como o menor retângulo delimitador; e se você tentar contar o fluxo de controle, terá problemas com os programas de modificação automática.
Nemo157
5

Rubi (40)

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

->

q["192.168.1.1"]
=> 3232235777
jsvnm
fonte
Boa idéia de usar regexp.
Hauleth
Muito esperto! Além disso, você pode escrever to_i 16como hexpara salvar alguns personagens.
Paul Prestidge
graças @chron que fez tanto este e ligação 4 caracteres mais curto
jsvnm
4

Ruby - 46 caracteres

require"ipaddr"
def f s;IPAddr.new(s).to_i;end
mordedor
fonte
Eu acho que isso é trapaça. ;-)
Chris Jester-Young
3

Golfscript - 21 caracteres

{'.'/{~}%{\256*+}*}:f
mordedor
fonte
+1 Boa solução sólida. Você não deseja que o GolfScript forneça operadores de mudança de bits? ;-) (Embora, amaldiçoado se eu sei quais símbolos devem ser obrigados a.)
Chris Jester-Young
3

Python 56 45

c=lambda x:eval('((('+x.replace('.','<<8)+'))
Alexandru
fonte
3

C ++ - muitos caracteres

#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
fonte
@ George Edison: usar o impulso ajuda a diminuir o número de caracteres? :)
Akira
3

PowerShell 66 61

Variação na resposta de 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
Ty Auvil
fonte
Argh, eu devo ter sido estúpido para não ter percebido que ...
Joey
3

AWK em ~ 47 caracteres

Iniciante aqui ... Hum, não sei como contar isso, mas sem o 'eco' são 47 caracteres no AWK. (Não é exatamente um golfe falso, mas está no buraco.)

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

Dia inteiro cedo para #tbt também, então eu realmente cumpri uma agenda !!! * 8-)

Dia da bandeira.

Blair Wyman
fonte
11
Bem-vinda! Você contaria apenas o corpo do que colocaria em um script awk. Veja esta resposta . No seu caso, você contaria apenas {print $1*16777216+$2*65536+$3*256+$4}. É claro que você precisaria mover o separador de campos para o programa, em vez de especificá-lo como um sinalizador.
Jonah
3

Bash - 46

Tabela de conteúdo

Você encontrará 4 versões de golfe diferentes:

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

Nova versão! 2018-11-15 Mais golfe, 46 caracteres

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

Explicação

  • Eu costumava $_jogar mais golfe.
  • A sintaxe ${1//./ }substituirá todos os pontos .por espaços .
  • então printfvai render algo como192<<(_-=8)|168<<(_-=8)|1<<(_-=8)|1<<(_-=8)|
  • então adicionaremos um 0depois do último OR | e
  • predefinido _para 32 . lerá a construção da esquerda para a direita, então $((_-=8))faça 24no 1º turno , 16no segundo e assim por diante.

em ação:

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

Por diversão: tentando obter $_conteúdo, depois disso:

echo $_
3232235777

; -b

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

Ok, está correto 32 - 4 x 8 = 0

Em uma função:

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

ou em um loop: -> 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

Primeiro post

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

Explicação:

  • A sintaxe ${1//./ }substituirá todos os pontos .por espaços.
  • set --definir parâmetros posicionais ($@=($1 $2 $3...) )
  • Assim set -- ${1//./ }será dividido $1por pontos e set $1, $2, $3e $4se string containg 3pontos (e sem espaços).

em ação:

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

ou em uma função:

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

ou em um loop: -> 61

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

em ação:

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

Outra versão com golfe diferente: 65

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

Amostra:

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

Em um loop (+14): 82

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

* ou um pouco mais feio: 70 *

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

onde printfdar um barbante como |192<<24 |168<<16 |1<<8|1<<24 |0<<16 |0<<8se tivéssemos que cortar finalmente <<2....

jogou golfe com mapfilemais tempo: 68

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

ou com laç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
}
F. Hauri
fonte
você poderia adicionar uma breve explicação? Eu tenho tentado entrar no bash golf e não sigo o que está acontecendo com a set --parte. obrigado.
Jonah #
@ Jonah: set -- foo barirá preencher $@com foo as $1e bar as $2.
F. Hauri
@Jonah Adicionada nova versão
F. Hauri
Obrigada pelo esclarecimento.
Jonah
Nova versão! mais golf, -1 char !!
F. Hauri
2

Windows PowerShell, 70

Abordagem ingênua:

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

Com o uso de System.Net.IPAddress: 76

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

Teste:

> '192.168.1.1'|I
3232235777
Joey
fonte
2

Befunge-93 - 36 caracteres

&"~"2+::8****&884**:**&884***&++++.@
MiffTheFox
fonte
2

Perl: DIY (para oneliners.) (40)

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

# Use valor em $ i

Função DIY (65):

sub atoi{my($i,$j)=(0,3);$i+=($_<<($j--*8))for split'.',shift;$i}
Kent Fredric
fonte
Você pode dividir por uma corda, para que salvar um personagem usando split'.', em vez desplit/\./
Covarde Anônimo
Com a versão de função, sim, mas a versão em linha não, porque você precisa split q{.}para contornar a necessidade de escapar citações shell: /
Kent Fredric
2

Haskell - 14 caracteres

(.) a=(256*a+)

uso no GHCi:

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

O único problema é que você deve colocar espaços à esquerda ou à direita do ponto, caso contrário, os números serão interpretados como ponto flutuante.

quasimodo
fonte
mente adicionando uma breve explicação?
Jonah #
o operador de ponto infix é redefinido para fazer o cálculo, muito inteligente mesmo!
Memorando
Isso é muito inteligente, mas não usa o formato de entrada correto (por causa dos espaços) #
12Me21
2

C # - 77 caracteres

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

JavaScript (45 caracteres)

Requer suporte para o .reduce()método Array, introduzido no ES5 e nas funções de seta .

f=(x)=>x.split('.').reduce((p,c)=>p<<8|c)>>>0
PleaseStand
fonte
Huh ... Eu não sabia >>> trabalhou assim (conversão de um inteiro de 32 bits sem sinal)
12Me21
2

Powershell, 47 43 bytes

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

Script de teste:

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

Resultado:

True: 3232235777
True: 168454180
True: 134744072
confuso
fonte
1

C # - 120 caracteres

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

Meu primeiro código de golfe - seja gentil;)

Kyle Rozendo
fonte
Você pode remover os espaços ao redor do seu primeiro '='. No entanto, seu principal problema é int overflow;). Lembre-se, um endereço IP ocupa 4 bytes completos.
Nellius 2/02
@ Nellius - muito bem. Eu nem pensei em verificar isso, basicamente verifiquei a compilação. Obrigado, irá corrigir agora.
Kyle Rozendo
1

D: 84 caracteres

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

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

    return n;
}
Jonathan M Davis
fonte
eu não sei D então me perdoe se for sensível a espaços em branco como python, mas isso não parece ser um jogo de golfe. você pode remover as quebras de linha duplas ou as quebras de linha entre instruções terminadas em ponto e vírgula?
Jonah
1

Python 3,2 (69)

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

PHP (sem builtins / eval) - 54

<foreach(explode(".",$argv[1])as$b)$a=@$a<<8|$b;echo$a;
Arnaud Le Blanc
fonte
Isso não deveria abrir com <?php, não apenas <?
TRiG 25/09/12
@TRiG, ​​acredito que você pode alterar o delimitador de abertura do PHP no arquivo de configuração. Útil neste caso.
Xeoncross 25/09/12
@Xeoncross. Ah Arrumado. Eu poderia tentar isso um dia, só para mexer com a cabeça dos meus colegas de trabalho.
TRiG 25/09/12
1

Perl, 14 caracteres:

sub _{unpack'L>',pop}

# Example usage
print _(10.10.104.36) # prints 168454180
Grimmy
fonte
5
Como você faz esses 14 caracteres? Conto 21.
Peter Taylor
1

C (gcc) -m32 / POSIX, 33 bytes

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

Experimente online!

Em uma plataforma big-endian, você poderia simplesmente definir uma macro com -Df=inet_atonpara 13 bytes .

Nwellnhof
fonte