Fonction de conversion d'entiers IPv4

17

Écrivez la fonction la plus courte pour convertir une adresse IP en sa représentation entière et la sortir sous forme d'entier.

Pour changer une adresse IPv4 en sa représentation entière, le calcul suivant est requis:

  • Divisez l'adresse IP en quatre octets.
  • (Octet1 * 16777216) + (Octet2 * 65536) + (Octet3 * 256) + (Octet4)

Exemple d'entrée

192.168.1.1           10.10.104.36           8.8.8.8

Exemple de sortie

3232235777            168454180              134744072
Kyle Rozendo
la source
2
Je pense que ce serait mieux s'il y avait une restriction en place interdisant les fonctions intégrées d'un langage.
Nathan Osman
@George - Oui, ça l'aurait été, mais les gens l'avaient déjà fait avant que je puisse mettre ça - honnêtement, je n'y ai pas pensé.
Kyle Rozendo

Réponses:

11

PHP - 21 caractères

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

MySQL - 20 caractères

SELECT INET_ATON(s);
ircmaxell
la source
8

Ruby (pas intégré / eval) - 47

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

Tester:

s["192.168.1.1"]
3232235777
Arnaud Le Blanc
la source
8

C: 79 caractères

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

EDIT: supprimé C ++, ne compilerait pas sans en-têtes; avec GCC, les appels de fonction printfet strtoldéclenchent des fonctions intégrées, donc les en-têtes peuvent être ignorés. Merci à @ugoren pour les conseils. Cela se compilera tel quel sans options supplémentaires pour gcc.

EDIT2: returnest en fait redondant :)

Nim
la source
utilisation très intelligente de main () :) .. ma version était de 116 octets.
akira
Je reçois un défaut de segmentation.
Nathan Osman
@George, quelle est votre contribution et comment la gérez-vous?
Nim
Je l'exécute avec mon UserScript
Nathan Osman
Cela ne fonctionnera pas en C ++, vous ne pouvez pas appeler récursivement main.
Scott Logan
7

Golfscript - 16 caractères

{[~]2%256base}:f

En tant que programme autonome, il est encore plus court à 11.

~]2%256base

Extrêmement simple. Évalue la chaîne d'entrée ( ~) et la place dans un tableau []. Puisque les .s dans la chaîne dupliquent le haut de la pile, nous ne prenons que tous les autres termes dans le tableau ( 2%). Nous avons maintenant un tableau qui représente essentiellement un nombre de base 256, nous utilisons donc une fonction intégrée pour effectuer la conversion. ( 256base).

Nabb
la source
très intelligent. je suppose que base256 est traitée différemment pour dire base10 ou base16 alors où 48 => 0?
gnibbler
@gnibbler: Je ne suis pas sûr de ce que vous proposez - la fonction de base gère toutes les bases de la même manière, par exemple {:B;{\B*+}*}:base(bien que la fonction réelle soit surchargée pour les conversions dans l'autre sens). Il est intéressant de noter que la conversion de base pour les chaînes est la même que pour les tableaux (car les chaînes ne sont que des tableaux sans imbrication, mais avec un format de sortie différent).
Nabb
ouais je pensais à des conversions de base de chaînes, donc je n'ai pas regardé assez attentivement basepour ma réponse
gnibbler
Très intelligent. Faites maintenant cela pour une adresse IPv6. :)
Ilmari Karonen
6

Befunge - 2x11 = 22 caractères

Si proche, Befunge gagnera un jour.

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

Explication

La plus grande caractéristique distinctive de Befunge est qu'au lieu d'être un ensemble linéaire d'instructions comme la plupart des langues; c'est une grille 2D d'instructions à caractère unique, où le contrôle peut circuler dans n'importe quelle direction.

>      v
^      <

Ces personnages changent la direction du contrôle lorsqu'ils sont touchés, cela fait la boucle principale.

 &+~1+

Cela entre un nombre et le pousse sur la pile ( &), fait sortir les deux premières valeurs de la pile, les ajoute et les repousse sur la pile ( +), entre un seul caractère et place sa valeur ascii sur la pile ( ~), puis pousse 1 sur la pile et les ajoute (1+ ).

L'interpréteur que j'ai utilisé renvoie -1 pour la fin de l'entrée, certains renvoient 0 à la place afin que la 1+partie puisse être supprimée pour eux.

      #v_.@

Le #fait sauter le caractère suivant, puis le _saute une valeur de la pile et s'il est nul envoie le contrôle à droite, sinon il le laisse à gauche. Si la valeur était zéro, .une valeur est supprimée de la pile et sortie sous forme d'entier et @arrête le programme. Sinon, venvoie le contrôle à la boucle de retour.

^*4*8*8<

Cela multiplie simplement la valeur supérieure de la pile par 256 et renvoie le contrôle au début.

Nemo157
la source
Pardonnez mon ignorance, mais cela devrait-il être 19 caractères? Je comprends pourquoi tu dis 2x11, mais pourquoi ça marche comme ça?
Kyle Rozendo
Befunge est un langage 2D, si vous recherchez celui >v<^qui est en fait la boucle principale de ce programme. Je suppose que dans ce cas, le contrôle ne passe pas réellement par ces 3 derniers espaces en bas, mais je trouve qu'il est plus facile de compter les programmes Befunge comme le plus petit rectangle englobant; et si vous deviez essayer de compter le flux de contrôle, vous avez des problèmes avec les programmes auto-modifiables.
Nemo157
5

Rubis (40)

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

->

q["192.168.1.1"]
=> 3232235777
jsvnm
la source
Belle idée d'utiliser regexp.
Hauleth
Très intelligent! Vous pouvez aussi écrire to_i 16que hexpour enregistrer quelques caractères.
Paul Prestidge
merci @chron qui a rendu ceci et le lien 4 caractères plus courts
jsvnm
4

Rubis - 46 caractères

require"ipaddr"
def f s;IPAddr.new(s).to_i;end
grignoteur
la source
Je pense que cela constitue de la triche. ;-)
Chris Jester-Young
3

Golfscript - 21 caractères

{'.'/{~}%{\256*+}*}:f
grignoteur
la source
+1 Bonne solution solide. Ne souhaitez-vous pas que GolfScript propose des opérateurs de décalage de bits? ;-) (Cependant, sacrément si je sais à quels symboles ils devraient être liés.)
Chris Jester-Young
3

Python 56 45

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

C ++ - beaucoup de caractères

#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
la source
@George Edison: l'utilisation de boost aide à réduire le nombre de caractères? :)
akira
3

PowerShell 66 61

Variation sur la réponse 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
la source
Argh, j'ai dû être stupide d'avoir raté ça ...
Joey
3

AWK en ~ 47 caractères

Débutant ici ... Hum, je ne sais pas comment compter cela, mais sans l '"écho", c'est 47 caractères dans AWK. (Pas exactement le golf de bogey, mais c'est dans le trou.)

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

Journée complète tôt pour #tbt, aussi, j'ai donc respecté un calendrier !!! * 8-)

Jour de la bannière.

Blair Wyman
la source
1
Bienvenue! Vous ne compteriez que le corps de ce que vous mettriez dans un script awk. Voir cette réponse . Dans votre cas, vous ne comptez que {print $1*16777216+$2*65536+$3*256+$4}. Bien sûr, vous devez déplacer le séparateur de champs dans le programme, plutôt que de le spécifier comme indicateur.
Jonah
3

Coup - 46

Table des matières

Vous trouverez 4 versions golfées différemment:

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

Nouvelle version! 2018-11-15 Plus de golf, 46 car.

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

Explication

  • J'ai utilisé $_pour plus de golf.
  • La syntaxe ${1//./ }remplacera tous les points .par des espaces .
  • printfva donc rendre quelque chose comme192<<(_-=8)|168<<(_-=8)|1<<(_-=8)|1<<(_-=8)|
  • nous ajouterons ensuite un 0dernier OU | et
  • préréglé _à 32 . lira la construction de gauche à droite, donc $((_-=8))faites 24au 1er quart de travail , 16au deuxième, et ainsi de suite.

en action:

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

Pour le plaisir: essayer d'obtenir du $_contenu, après cela:

echo $_
3232235777

; -b

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

Ok c'est vrai 32 - 4 x 8 = 0

Dans une fonction:

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 en boucle: -> 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

Premier poste

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

Explication:

  • La syntaxe ${1//./ }remplacera tous les points .par des espaces .
  • set --définir les paramètres de position ( $@=($1 $2 $3...))
  • Ainsi , set -- ${1//./ }sera divisé $1par points et ensemble $1, $2, $3et $4si la chaîne containg 3points (sans espace).

en action:

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

ou dans une fonction:

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

ou en boucle: -> 61

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

en action:

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

Une autre version a joué différemment: 65

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

Échantillon:

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

En boucle (+14): 82

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

* ou un peu plus moche: 70 *

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

printfdonner une chaîne comme|192<<24 |168<<16 |1<<8|1<<24 |0<<16 |0<<8 nous devons enfin couper <<2....

golfé avec mapfile, plus: 68

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

ou avec boucle: 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
la source
pourriez-vous ajouter une brève explication? j'ai essayé d'entrer dans le golf bash et je ne suis pas suivre ce qui se passe avec la set --partie. Merci.
Jonah
@Jonah: set -- foo barva remplir $@avec foo comme $1et bar comme $2.
F.Hauri
@Jonah Ajout d'une nouvelle version
F. Hauri
Merci pour l'explication.
Jonah
Nouvelle version! plus golfé, -1 char !!
F.Hauri
2

Windows PowerShell, 70

Approche naïve:

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

Avec l'utilisation de System.Net.IPAddress: 76

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

Tester:

> '192.168.1.1'|I
3232235777
Joey
la source
2

Befunge-93 - 36 personnages

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

Perl: DIY (pour oneliners.) (40)

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

# Utilisez la valeur en $ i

Fonction bricolage (65):

sub atoi{my($i,$j)=(0,3);$i+=($_<<($j--*8))for split'.',shift;$i}
Kent Fredric
la source
Vous pouvez diviser par une chaîne, donc vous enregistrez un caractère en utilisant split'.'plutôt quesplit/\./
lâche anonyme
Avec la version de la fonction, oui, mais la version en ligne non, car vous auriez besoin split q{.}de contourner le besoin d'échapper aux citations du shell: /
Kent Fredric
2

Haskell - 14 caractères

(.) a=(256*a+)

utilisation dans GHCi:

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

Le seul problème est que vous devez mettre des espaces à gauche ou à droite du point, sinon les nombres seront interprétés comme des virgules flottantes.

quasimodo
la source
vous voulez ajouter une brève explication?
Jonah
l'opérateur infixe de points est redéfini pour faire le calcul, très intelligent en effet!
mémo
C'est très intelligent, mais il n'utilise pas le format d'entrée correct (à cause des espaces)
12Me21
2

C # - 77 caractères

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

JavaScript (45 caractères)

Nécessite la prise en charge de la .reduce()méthode Array introduite dans ES5 et des fonctions fléchées .

f=(x)=>x.split('.').reduce((p,c)=>p<<8|c)>>>0
Veuillez vous lever
la source
Huh ... Je ne savais pas >>> fonctionnait comme ça (conversion en entier 32 bits non signé)
12Me21
2

Powershell, 47 43 octets

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

Script de test:

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

Production:

True: 3232235777
True: 168454180
True: 134744072
mazzy
la source
1

C # - 120 caractères

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

Mon premier golf de code - soyez doux;)

Kyle Rozendo
la source
Vous pouvez supprimer les espaces autour de votre premier «=». Cependant, votre problème principal est le débordement int;). N'oubliez pas qu'une adresse IP occupe 4 octets complets.
Nellius
@Nellius - tout à fait raison. Je n'ai même pas pensé à vérifier cela, essentiellement vérifié lors de la compilation. Merci, corrigera maintenant.
Kyle Rozendo
1

D: 84 caractères

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
la source
je ne sais pas D alors pardonnez-moi si c'est sensible aux espaces comme le python, mais ça n'a pas l'air golfé. pouvez-vous supprimer les sauts de ligne doubles ou les sauts de ligne entre les instructions terminées par un point-virgule?
Jonah
1

Python 3.2 (69)

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

PHP (pas de builds / eval) - 54

<foreach(explode(".",$argv[1])as$b)$a=@$a<<8|$b;echo$a;
Arnaud Le Blanc
la source
Cela ne devrait-il pas s'ouvrir avec <?php, pas seulement <?
TRiG
@TRiG, ​​je crois que vous pouvez changer le délimiteur d'ouverture PHP dans le fichier de configuration. Utile dans ce cas.
Xeoncross
@Xeoncross. Ah. Soigné. Je pourrais essayer un jour, juste pour jouer avec la tête de mes collègues.
TRiG
1

Perl, 14 caractères:

sub _{unpack'L>',pop}

# Example usage
print _(10.10.104.36) # prints 168454180
Grimmy
la source
5
Comment faites-vous ces 14 caractères? Je compte 21.
Peter Taylor
1

C (gcc) -m32 / POSIX, 33 octets

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

Essayez-le en ligne!

Sur une plate - forme big-endian, vous pouvez définir simplement une macro avec -Df=inet_atonpour 13 octets .

nwellnhof
la source