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

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:




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

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


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


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.


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

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


3

Golfscript - 21 caractères

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

+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

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

@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

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.


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
}

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

2

Befunge-93 - 36 personnages

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

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}

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.


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

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

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

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


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

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

1

PHP (pas de builds / eval) - 54

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

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

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 .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.