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

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:




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

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


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)


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.


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

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


3

Golfscript - 21 caracteres

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

+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)+'))

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

@ 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

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.


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
}

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

2

Befunge-93 - 36 caracteres

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

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}

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.


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

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

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

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


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

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

1

PHP (sem builtins / eval) - 54

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

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

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 .

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.