IP adresi mi, değil mi?


25

Ağ tarama aracınız giriş konusunda can sıkıcı bir şekilde seçicidir ve uygunsuz karakterler içeren veya doğru biçimlendirilmemiş bir IPv4 adresini beslerseniz hemen kilitlenir.

IPv4 adresi, noktalarla ayrılmış dört sayı olarak yazılmış 32 bitlik sayısal bir adrestir . Her numara sıfır ila 255 olabilir .

Bu çökmelerden kaçınmak için girişi önceden doğrulamak için bir araç yazmamız gerekiyor ve özel aracımız seçici: Geçerli bir format, a.b.c.da, b, c ve d gibi gözükecek :

  • Bir olabilir 0veya doğal sayı hiçbir başındaki sıfırlar .
  • 0 - 255 (dahil) arasında olmalıdır.
  • Meli değil gibi özel simgeleri içeren +, -, ,ve diğerleri.
  • Ondalık (temel 10) olmalı

Giriş : Bir dize

Çıktı : Truthy veya Falsey değeri (isteğe bağlı değerler de kabul edilir)

Test Durumları :

Input            |  Output  |  Reason
                 |          |
- 1.160.10.240   |  true    |
- 192.001.32.47  |  false   |  (leading zeros present)
- 1.2.3.         |  false   |  (only three digits)
- 1.2.3          |  false   |  (only three digits)
- 0.00.10.255    |  false   |  (leading zeros present)
- 1.2.$.4        |  false   |  (only three digits and a special symbol present)
- 255.160.0.34   |  true    |
- .1.1.1         |  false   |  (only three digits)
- 1..1.1.1       |  false   |  (more than three periods)
- 1.1.1.-0       |  false   |  (special symbol present)
- .1.1.+1        |  false   |  (special symbol present)
- 1 1 1 1        |  false   |  (no periods)
- 1              |  false   |  (only one digit)
- 10.300.4.0     |  false   |  (value over 255)
- 10.4F.10.99    |  false   |  (invalid characters)
- fruit loops    |  false   |  (umm...)
- 1.2.3.4.5      |  false   |  (too many periods/numbers)
- 0.0.0.0        |  true    |
- 0.0 0.0.       |  false   |  (periods misplaced)
- 1.23..4        |  false   |  (a typo of 1.2.3.4)
- 1:1:1:1:1:1:1:1|  false   |  (an IPv6 address, not IPv4)

Bu , yani en az bayt kazanacak!

Kullanıcılar için not - biraz daha test senaryosu eklemek istiyorsanız, memnuniyetle karşılanırsınız (düzenleme önererek). Ancak, lütfen test durumlarının kendilerini tekrar etmediğinden emin olun! Teşekkürler


10
Testcases öner: 1.1.1.1.1, 1.1.1.1., .1.1.1, 1..1.1, 1..1.1.1, 1.1.1.0, 1.1.1.-0, 1.1.1.+1, 1.1.1.1E1, 1.1.1.256, 1.1.1.0x1, 255.255.255.255, 0.0.0.0, 'or 1=1--, <empty string>, 1 1 1 1, 1,1,1,1.
tsh

5
"1.2.3.4.5" (çok uzun IP'leri ekarte etmek için) ve "999.0.0.0" (çok büyük IP'leri ekarte etmek için) ekleyen test önerileri yapın.
Triggernometry

5
Muhtemelen biraz seçicidir, ancak muhtemelen "IP adresleri" yerine "IPv4 adreslerini" belirtmelisiniz - veya en azından bir yerde sadece IPv4 adreslerini kastettiğinizi belirtmelisiniz - aksi halde 1234: 5678 :: 1 geçerli bir IP adresi olmalıdır (bununla birlikte açıklamadan bu amaçlanmadığı açıktır :)
psmears

3
@Criggie Öncül aslında tüm gerçek IP4 kurallarını (bahsettiğiniz gibi) kontrol etmiyor, giriş dizesinin yalnızca çok özel bir biçimde giriş yapılmasına izin veren başka (muhtemelen kötü yazılmış) bir uygulamada çökmemesini sağlamak . Ayrıca, 30'dan fazla yanıtı olan bir meydan okuma kuralını değiştirmeyeceğiz.
BradC

2
@Criggie RFC'nin "Adreslerin dört oktet sabit uzunlukta olduğunu" bildirdiğini belirtmeye değer. Bence atıfta bulunduğun saçak davaları bu zorluktan daha uzman.
Poke

Yanıtlar:


26

X86_64 makine kodu: 18 16 bayt

Düzenleme: Bu cevap, pek işe yaramadı.

  1. Ben kullanıyorum inet_ptonben extern gerek vasıta standart C kütüphaneleri, gelen. Ama dıştaki sayımı bayt sayıma dahil etmedim.
  2. Asıl adresin sonucu olarak kırmızı bölgeyi kullandım ancak kırmızı bölgeyi de kullanabilecek bir işlev kullandım. Neyse ki makinemde yok ama bazı garip standart kütüphane yapıları tanımsız davranışa neden olabilecek şekilde kullanabilir.

Ve evet, her şey zaten zaten yazılı bir işlev tarafından yapılıyor

Her neyse, sahip olduğum şey bu: 48 89 fe 6a 02 5f 48 8d 54 24 80 e9 00 00 00 00

Montaj:

section .text
    extern inet_pton
    global ipIsValid

ipIsValid:
    mov rsi, rdi
    ;mov rdi, 2 ; change to 10 for ipv6
    push 2
    pop rdi ; thank you peter
    lea rdx, [rsp - 128]
    jmp inet_pton

Açıklama:

Bir göz atın inet_pton(3). Bir dize IP adresi alır ve kullanabileceğiniz bir arabellek koyar struct sockaddr. 3 argüman alır: adres ailesi ( AF_INET(ipv4), 2 veya AF_INET6(ipv6), 10), ip adresinin dizesi ve çıktıya bir işaretçi. Başarı durumunda 1, geçersiz bir adres için 0, adres ailesinin ne olmadığı AF_INETveya ne zaman olduğu (-1 AF_INET6.

Bu yüzden dizeyi ikinci argüman için register'a taşıdım, ilk registerı 2'ye ayarlıyorum ve üçüncü registerı kırmızı bölgeye (yığın göstergesinin altında 128 bytes) ayarlıyorum çünkü sonuçları umursamıyorum. Sonra ben sadece can jmpiçin inet_ptonve düz arayana bu dönüşü edelim!

Davalarınızı test etmek için bu hızlı test programını başlattım:

#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/ip.h>

extern int ipIsValid(char *);

int main(){
    char *addresses[] = {
        "1.160.10.240",
        "192.001.32.47",
        "1.2.3.",
        "1.2.3",
        "0.00.10.255",
        "1.2.$.4",
        "255.160.0.34",
        ".1.1.1",
        "1..1.1.1",
        "1.1.1.-0",
        ".1.1.+1",
        "1 1 1 1",
        "1",
        "10.300.4.0",
        "10.4F.10.99",
        "fruit loops",
        "1.2.3.4.5",
        NULL
    };

    for(size_t i = 0; addresses[i] != NULL; ++i){
        printf("Address %s:\t%s\n", addresses[i],
            ipIsValid(addresses[i]) ? "true" : "false");
    }
    return 0;
}

İle nasm -felf64 assembly.asmderleyin, derleyin gcc -no-pie test.c assembly.ove şunları elde edin:

Address 1.160.10.240:   true
Address 192.001.32.47:  false
Address 1.2.3.: false
Address 1.2.3:  false
Address 0.00.10.255:    false
Address 1.2.$.4:    false
Address 255.160.0.34:   true
Address .1.1.1: false
Address 1..1.1.1:   false
Address 1.1.1.-0:   false
Address .1.1.+1:    false
Address 1 1 1 1:    false
Address 1:  false
Address 10.300.4.0: false
Address 10.4F.10.99:    false
Address fruit loops:    false
Address 1.2.3.4.5:  false

Arayanın geçmesi AF_INETveya AF_INET6işleve geçmesi gerekiyorsa, bunu çok daha küçük yapabilirim.


4
Bunu asm ile yaptigini seviyorum. Ve bunu anlayamayacaklarına (test koduna ek olarak) açıkladığın gerçeği daha da iyi. Asm olarak yapabileceğimi söylemek değil; çok uzun yıllar geçti ama açıklamanızın (ve dolayısıyla sürecin) tam olarak ne dediğini (ne yaptığını) görecek kadarını hatırlıyorum. İyi iş.
Pryftan

4
e9 00 00 00 00bir jmp near $+5, bir değil jmp inet_pton. Opcode sağlarsanız, dahil olan inet_ptonkısmı dahil etmelisiniz , boş bırakmayınız
l4m2

1
15 bytes-TIO 32bit x86
Logern

3
extern'i cevap başlığına dahil etmelisiniz, çünkü program bunu gerektirir ve tüm platformlarda mevcut değildir.
qwr

1
"mov rdi, 2" -2 bayt için "push 2 / pop rdi" olabilir. Ayrıca, demontajın yanlış olduğunu veya kodun yanlış olduğunu unutmayın. Ya "mov edi" (rdi değil) ya da eksik bir önek var.
Peter Ferrie

13

Java (JDK) , 63 bayt

s->("."+s).matches("(\\.(25[0-5]|(2[0-4]|1\\d|[1-9])?\\d)){4}")

Çevrimiçi deneyin!

Kredi

  • Kevin Cruijssen sayesinde -1 bayt
  • Daha önce başarısız olan durumu göstermek için 14 m 2 .1.1.1.1.

İzleyen yarı-kolonu kaldırmayı unuttun. ;) Ve yorumlarda olanlar da dahil tüm test durumlarında çalıştığını doğrulayabilirim. Golf oynamak için bazı şeyler görüp görmeyeceğim.
Kevin Cruijssen

3
Başarısız oldu.1.2.3.4
l4m2

Açıkça 0/1 gerektirdiğinde boolean kullanmasına izin verilir mi?
l4m2

1
@ l4m2 Orijinal soru Geçerli / Geçersiz idi. Bu yüzden burada herhangi bir truthy / falsey değerinin kabul edilebilir olduğunu varsayıyorum.
Kevin Cruijssen

Output: 0 or 1ve Java otomatik olarak bool-> int
l4m2

12

JavaScript (Node.js) , 43 bayt

x=>x.split`.`.map(t=>[t&255]==t&&[])==`,,,`

Çevrimiçi deneyin!

JavaScript (Node.js) , 46 bayt

x=>x.split`.`.every(t=>k--&&[t&255]==t,k=4)*!k

Çevrimiçi deneyin!

ikinci el araç Arnauld

JavaScript (Node.js) , 54 53 51 bayt

x=>x.split`.`.every(t=>k--*0+t<256&[~~t]==t,k=4)*!k

Çevrimiçi deneyin!

-2B 0+t<256, Patrick Stephansen'dan -1B, girişi önlemek için + 1B1.1.1.1e-80

RegExp çözümü 58 54 bayt

s=>/^((2(?!5?[6-9])|1|(?!0\d))\d\d?\.?\b){4}$/.test(s)

3 bayt için teşekkür ederiz


Bazı test vakaları ekledim!
rv7


1
@KevinCruijssen 0.0.0.0burada gerçek biri. Sadece neden SQL Injection burada?
l4m2

Ah bekle, cümle tanımındaki cümleyi yanlış yorumluyorum. 0.0.0.0gerçekten de hakikaten. Bu benim cevabımı da golf oynayacak .. (SQL enjeksiyonu ile ne kastediyorsun
?:

1
@ l4m2 Bir IP adresi gibi görünmeyen testislere ihtiyacımız olduğu için ekledim.
tsh

11

PHP , 39 36 bayt

<?=+!!filter_var($argv[1],275,5**9);

Çevrimiçi deneyin!

275 sabite benzer FILTER_VALIDATE_IP

Sabit yerine 5 ** 9 kullanılıyor FILTER_FLAG_IPV4. Bu yeterli, çünkü 5**9 & FILTER_FLAG_IPV4Benoit Esnard'ın da belirttiği gibi PHP'nin arka planda tam olarak yaptığı gibi gerçek olan bir gerçek.

Burada, filter_vargeçerli bir IPv4 adresiyse ilk argümanı, değilse de false değerini döndürür. İle +!!, zorluğun gerektirdiği çıktıyı üretiyoruz.


3
Burada 3 bayt 5**9yerine 1048576tasarruf kullanılır : PHP &, IPv4 / IPv6 bayraklarını test etmek için kullanır , bu nedenle 1048576 ve 2097151 arasındaki herhangi bir sayı geçerlidir.
Benoit Esnard

2018-10-22 09: 17'de yazılırken 2018-10-22 09: 17: 34UTC'de yazılmış olan (temelde) cevabımın cevabını aşağılamıştım (temelde) cevabım: codegolf.stackexchange.com/a/174470/14732 21: 55UTC. @BenoitEsnard tarafından verilen 1 bayt optimizasyona geri dönsem bile, cevabım işlevsellik sizinkiyle tamamen aynı.
Ismael Miguel,

2
Özür dilemeliyim ki, cevabınızı görmedim, ancak beste yaparken, PHP'de bu soruya gönderim yoktu (dediğiniz gibi, zaman farkı beş dakikadan az).
oktupol

Biliyorum ve anlıyorum. Sadece şimdi seninkileri farkettim. Benimkini geri alabilirim ve sen optimizasyona devam et. Fakat cevabın birbirinden yeterince farklı olup olmadığını bilmiyorum.
Ismael Miguel,

17
@IsmaelMiguel Eğer başlıyorsa sizinki orada olmazsa, bunun için birini düşüremezdim. 5 dakikalık bir farkla, sadece mantıklı olmakla kalmıyor, yazarın kendisi bile söylemeden bile görüldüğü gibi neredeyse kesin bir durum.
Duncan X Simpson

11

PHP, 36 Bayt

echo(ip2long($argv[1])===false?0:1);

ip2longiyi bilinen bir yerleşik işlevdir .



Bu, daha yeni sürümlerde bulunan kodlanmamış özellikleri kullanıyor gibi görünüyor (PHP7 + 'dan kaynaklandığını tahmin ediyorum). PHP 4 ve 5 için bunun eksik IP'leri kabul ettiğini unutmayın.
Ismael Miguel,



1
Bu, 1, 2, vb. Herhangi bir tamsayı beslerseniz başarılı olur. Olması gerektiğini düşünmeyin. Ve ayrıca 100.100.100 gibi bir şey beslerseniz
nl-x

10

Perl 6 , 22 21 20 bayt

Phil H. sayesinde -1 bayt

{?/^@(^256)**4%\.$/}

Çevrimiçi deneyin!

açıklama

{                  }  # Anonymous Block
  /               /   # Regex match
   ^             $    # Anchor to start/end
    @(    )           # Interpolate
      ^256            #   range 0..255,
                      #   effectively like (0|1|2|...|255)
           **4        # Repeated four times
              %\.     # Separated by dot
 ?                    # Convert match result to Bool

3
Dostum, Perl 6'nın regex'lerini bulmak için daha fazla zaman harcamam gerek %Değiştiricinin ikisinde de yoktu . Acaba tüm 256**4olasılıkları kontrol etmeye çalışır mı?
Jo King

1
Bunun yerine <{^256}>, aralığı yalnızca @(^256)-1 char TIO için bir diziye dönüştürebilirsiniz . Kod bloğunu bir diziye dönüştürerek, aynı zamanda çok daha hızlı bir şekilde daha hızlı hale gelir (> 30 yerine 0.4s).
Phil H

@PhilH Cool, teşekkürler. Denedim $(^256)ama şimdi bunun neden işe yaramadığını anladım.
nwellnhof

9

05AB1E , 26 24 23 22 23 bayt

'.¡©g4Q₅Ý®å`®1šDïþJsJQP

@Emigna sayesinde -1 bayt . Hata düzeltme
testi durumu için +1 bayt 1.1.1.1E1hatalı, hatalı bir sonuç verdi.

Çevrimiçi deneyin veya tüm test durumlarını doğrulayın .

Açıklama:

'.¡              '# Split the (implicit) input by "."
   ©              # Save it in the register (without popping)
    g4Q           # Check that there are exactly 4 numbers
    ₅Ý®å          # Check for each of the numbers that they are in the range [0,255],
        `         # and push the result for each number separated onto the stack
    ®1šDïþJsJQ    # Check that each number does NOT start with a "0" (excluding 0s itself),
                  # and that they consist of digits only
              P   # Check if all values on the stack are truthy (and output implicitly)

1
Kullanılacak gerekir Āyerine<d
Emigna

Korkarım @MagicOctopusUrn o başarısız 1.1.1.1E1, 1..1.1.1, 1.1.1.1., 192.00.0.255, ve 0.00.10.255. (Not: 1.1.1.1E1þ
Katıl

Yeterince adil, bir şey özledim düşündüm.
Magic Octopus Urn,

@MagicOctopusUrn Asıl mesele, 05AB1E, baştaki 0'lara sahip sayıları, hatta string olarak bile olmayanlara eşit şekilde görmek. Kullandığım yüzden mi DïþJsJQçek ïbir 0 kaldırmak için int için döküm ve þsadece yaprakları basamak gibi şeyler kaldırarak E, -vb :) test durumu içindir 0.00.10.255çünkü 00010255ve 0010255eşit olacaktır.
Kevin Cruijssen

Evet aynı saçmalıktan geçtim, tüm sayıların tersine çevrilmesi, bu durumlar dışında oldukça iyi çalıştı. Bazı problemler için faydalı olan özellikler diğerleri için neredeyse hataya dönüşürken ilginçtir.
Magic Octopus Urn,

6

PowerShell, 59 51 49 bayt

-8 bayt, teşekkürler @AdmBorkBork

-2 bayt trueveya falseyazar tarafından izin verildi

try{"$args"-eq[IPAddress]::Parse($args)}catch{!1}

Test komut dosyası:

$f = {

try{"$args"-eq[IPAddress]::Parse($args)}catch{!1}

}

@(
    ,("1.160.10.240" , $true)
    ,("192.001.32.47" , $false)
    ,("1.2.3." , $false)
    ,("1.2.3" , $false)
    ,("0.00.10.255" , $false)
    ,("192.168.1.1" , $true)
    ,("1.2.$.4" , $false)
    ,("255.160.0.34" , $true)
    ,(".1.1.1" , $false)
    ,("1..1.1.1" , $false)
    ,("1.1.1.-0" , $false)
    ,("1.1.1.+1" , $false)
    ,("1 1 1 1" , $false)
    ,("1"            ,$false)
    ,("10.300.4.0"   ,$false)
    ,("10.4F.10.99"  ,$false)
    ,("fruit loops"  ,$false)
    ,("1.2.3.4.5"    ,$false)

) | % {
    $s,$expected = $_
    $result = &$f $s
    "$($result-eq$expected): $result : $s"
}

Çıktı:

True: True : 1.160.10.240
True: False : 192.001.32.47
True: False : 1.2.3.
True: False : 1.2.3
True: False : 0.00.10.255
True: True : 192.168.1.1
True: False : 1.2.$.4
True: True : 255.160.0.34
True: False : .1.1.1
True: False : 1..1.1.1
True: False : 1.1.1.-0
True: False : 1.1.1.+1
True: False : 1 1 1 1
True: False : 1
True: False : 10.300.4.0
True: False : 10.4F.10.99
True: False : fruit loops
True: False : 1.2.3.4.5

Açıklama:

Komut, bir .NET nesnesi ( IPAdresi) oluşturmak için bir argüman dizesini ayrıştırmaya çalışır .

  • $trueEğer objectyaratılmışsa return ve argüman dizgisi object(normal adrese göre object.toString()) dizgesinin gösterilmesine eşittir.
  • $falseaksi takdirde geri dön

PowerShell, 59 56 54 bayt, '.NET lib kullanmayın' alternatifi

-3 bayt trueveya falseyazara izin verilir

-2 bayt, serin regexp @ Deadcode sayesinde .

".$args"-match'^(\.(2(?!5?[6-9])|1|(?!0\B))\d\d?){4}$'

Çevrimiçi deneyin!

Orjinal düzenli ifade için @ Olivier Grégoire .


1
Sol taraf bir dize olduğundan, |% t*gPowerShell otomatik -eqolarak dize olarak sağ tarafa geçeceğinden aramanıza gerek yoktur . -try{+("$args"-eq[IPAddress]::Parse($args))}catch{0}
AdmBorkBork

Regex'imi kullanarak ".NET lib kullanmayın" sürümünden 2 bayt ayırabilirsiniz (tabii ki benim sürümümde bulunamadığı bir dönem ekleme hilesine uyarlanmıştır) tio.run/…
Deadcode

5

C (gcc) / POSIX, 26 bayt

f(s){s=inet_pton(2,s,&s);}

Çevrimiçi deneyin!

TIO'da 64 bit kod olarak çalışır, ancak muhtemelen sizeof(int) == sizeof(char*)başka platformlarda da olmasını gerektirir .


@TobySpeight Evet, x86 kullanıyorsanız, muhtemelen 32-bit modunda ( -m32) denemelisiniz .
nwellnhof

İşe aldım, (burada bir ILP32 sistemine erişim yok) solarak geçerek char*ve evet, karıştırıyordum inet_aton().
Toby Speight

5

PHP 7+, 37 35 32 bayt

Bu yerleşik işlevini kullanır filter_varüzere, bir IPv4 adresi olduğunu doğrulamak .

Çalışması için anahtarı ibir GET isteğinin üzerine geçirmeniz gerekir .

<?=filter_var($_GET[i],275,5**9);

Sonuca bağlı olarak hiçbir falsysonuç ( sonuç için) veya IP (sonuç için) çıktısını vermez truthy.

Bunu deneyebilirsiniz: http://sandbox.onlinephpfunctions.com/code/639c22281ea3ba753cf7431281486d8e6e66f68e http://sandbox.onlinephpfunctions.com/code/ff6aaeb2b2d0e0ac43f48125de0549320bc071b4


Bu doğrudan aşağıdaki değerleri kullanır:

  • 275 = FILTER_VALIDATE_IP
  • 1 << 20 = 1048576 = FILTER_FLAG_IPV4
  • 5 ** 9 = 1953125 (1048576 için gerekli biti "1" olan)

Bana 1 bayt kazandıran bu ipucu için Benoit Esnard'a teşekkür ederim !

Bana zorluktaki değişiklikleri hatırlattığın için Titus'a teşekkür ederim .


Fonksiyonu kullanmaya çalıştım ip2long, ancak tamamlanmamış IP adresleriyle çalışıyor.

Tamamlanmamış IPv4 adresleri bu mücadelede geçersiz sayılır.

If they were allowed, this would be the final code (only for PHP 5.2.10):

<?=ip2long($_GET[i]);

Currently, it isn't explicit in the documentation that this will stop working (when passed an incomplete ip) with newer PHP versions.

After testing, confirmed that that was the case.

Thanks to nwellnhof for the tip!


Using 5**9 instead of 1<<20 saves one byte here: PHP uses & to test the IPv4 / IPv6 flags, so any number between 1048576 and 2097151 is valid.
Benoit Esnard

In newer PHP versions, ip2long doesn't allow incomplete addresses.
nwellnhof

@BenoitEsnard Thank you! I've added it to the answer
Ismael Miguel

@nwellnhof After testing, I confirm that that is the case. However, I don't think it is a good idea to use it, since it isn't explicitly documented.
Ismael Miguel

+!! is not required; the OP now accepts arbitrary truthy values.
Titus

5

Python 3: 81 78 70 69 66 bytes

['%d.%d.%d.%d'%(*x.to_bytes(4,'big'),)for x in range(16**8)].count

Loop over all possible IPv4 addresses, get the string representation and compare it to the input. It uh... takes a while to run.

EDIT: Removed 3 bytes by switching from full program to anonymous function.

EDIT2: Removed 8 bytes with help from xnor

EDIT3: Removed 1 byte by using an unpacked map instead of list comprehension

EDIT4: Removed 3 bytes by using list comprehension instead of the ipaddress module


2
I think your anonymous function can just be [str(ip_address(x))for x in range(256**4)].count. Also, 256**4 can be 16**8.
xnor

5

C# (Visual C# Interactive Compiler), 84 79 65 bytes

s=>s.Split('.').Sum(t=>byte.TryParse(t,out var b)&t==b+""?1:5)==4

Try it online!

-5 and -14 bytes saved thanks to @dana!

# C# (Visual C# Interactive Compiler), 61 bytes

s=>s.Count(c=>c==46)==3&IPAddress.TryParse(s,out IPAddress i)

Try it online!

This is a work in progress. The code use System.Net (+17 bytes if you count it). if you wonder why I count and parse:

The limitation with IPAddress.TryParse method is that it verifies if a string could be converted to IP address, thus if it is supplied with a string value like "5", it consider it as "0.0.0.5".

source

As @milk said in comment, it will indeed fail on leading zeroes. So, the 61 bytes one is not working.


1
@dana great. Nicely done! Four more and it will beat the 61 bytes solutions!
aloisdg says Reinstate Monica

4

Python 2, 85 82 81 bytes

-1 byte thanks to Kevin Cruijssen

from ipaddress import*
I=input()
try:r=I==str(IPv4Address(I))
except:r=0
print~~r

Try it online!

113 byte answer is deleted as it fails for 1.1.1.1e-80


1
You can golf print 1*r to print~~r. +1 though, since it seem to work for all possible test cases suggested thus far. PS: Your 113 byte answer fails for 1.1.1.1e-80.
Kevin Cruijssen

@KevinCruijssen Thanks! Didn't think about such notation of numbers
Dead Possum

Isn't ipaddress a Python 3 module?
Farhan.K

@Farhan.K Dunno, but it works in TIO
Dead Possum

4

Japt, 17 15 bytes

q.
ʶ4«Uk#ÿòs)Ê

Try it or run all test cases or verify additional test cases from challenge comments


Explanation

We split to an array on ., check that the length of that array is equal to 4 AND that the length when all elements in the range ["0","255"] are removed from it is falsey (0).

                 :Implicit input of string U
q.               :Split on "."
\n               :Reassign resulting array to U
Ê                :Length of U
 ¶4              :Equals 4?
   «             :&&!
    Uk           :Remove from U
      #ÿ         :  255
        ò        :  Range [0,255]
         s       :  Convert each to a string
          )      :End removal
           Ê     :Length of resulting array

Nice answer. Also verified for all suggested test cases thus far. Curious to see that explanation.
Kevin Cruijssen

2
@KevinCruijssen, explanation added. Thanks for those additional test cases.
Shaggy

3

Mathematica, 39 31 bytes

Original version:

¬FailureQ[Interpreter["IPAddress"][#]]&

Modified version (thanks to Misha Lavrov)

 AtomQ@*Interpreter["IPAddress"]

which returns True if the input is a valid IP address (try it).

In case you insist on getting 1 and 0 instead, then an additional 7 bytes would be necessary:

Boole/@AtomQ@*Interpreter["IPAddress"]

Since Interpreter["IPAddress"] returns a string for valid input, and some complicated failure object for invalid input, we can test for valid inputs with AtomQ[Interpreter["IPAddress"][#]]&, which can be further shortened to the function composition AtomQ@*Interpreter["IPAddress"]. Try it online!
Misha Lavrov

Fails on an IPv6 address like 2001:0db8:85a3:0000:0000:8a2e:0370:7334.
lirtosiast


3

Python 2, 93 89 67 53 bytes

[i==`int(i)&255`for i in input().split('.')]!=[1]*4>_

Try it online!

Thanks to Dennis for shaving another 14 bytes on the internal comparisons and exit code.

Special thanks to Jonathan Allan for shaving 22 bytes & a logic fix! Pesky try/except begone!

Taking properly formatted strings instead of raw bytes shaves off 4 bytes, thanks Jo King.


Your check can be golfed to i==`int(i)&255` . Also, you can force an error with [...]!=[1]*4>_, since you're using exit codes anyway. Try it online!
Dennis

@Dennis I don't understand what >_ does. The bitwise and is quite ingenious though... I was unsuccessful in combining those myself.
TemporalWolf

2
If the != returns False, Python short-circuits and nothing happens; the interpreter exits normally. If it returns True, >_ raises a NameError, because the variable _ is undefined.
Dennis

Figures I chain comparisons in my answer and then miss the obvious result in your comment. Thanks for the explanation.
TemporalWolf

3

sfk, 176 bytes

* was originally Bash + SFK but TIO has since added a proper SFK wrapper

xex -i "_[lstart][1.3 digits].[1.3 digits].[1.3 digits].[1.3 digits][lend]_[part2]\n[part4]\n[part6]\n[part8]_" +xed _[lstart]0[digit]_999_ +hex +linelen +filt -+1 -+2 +linelen

Try it online!


Would first checking the error printout from nc [addr] 1 -w1 shorten this?

@Rogem nc accepts leading zeroes as well as IPv6 addresses, so I'd still have to handle those - and this is intended more as a sfk answer than a shell answer anyway.
Οurous

3

Python3 Bash* 60

*Also other shells. Any one for which the truthy/falsy test passes on a program exit code

read I
python3 -c "from ipaddress import*;IPv4Address('$I')"

Explanation

The trouble with a pure Python solutions is that a program crashing is considered indeterminate. We could use a "lot" of code to convert an exception into a proper truthy/fasly value. However, at some point the Python interpreter handles this uncaught exception and returns a non-zero exit code. For the low-low cost of changing languages to your favourite Unix shell, we can save quite a bit of code!

Of course, this is vulnerable to injection attacks... Inputs such as 1.1.1.1'); print('Doing Something Evil are an unmitigated threat!


(Explanation it is (not Explaination).)
Peter Mortensen

@PeterMortensen Yikes. It was even underlined in red. My browser tried to save me, but I wouldn't listen. Thanks for catching that!
Sompom

Full programs are allowed to output via exit codes, therefore this could be 43 bytes.
ბიმო

@BMO Interesting. Thanks for pointing that out! I think the problem definiiton changed from "Truthy/Falsy" to also allowing arbitrary output since I posted this, but I could have just not noticed before :)
Sompom

3

ECMAScript pure regex, 41 bytes

^((2(?!5?[6-9])|1|(?!0\B))\d\d?\.?\b){4}$

Try it online!
Try it on regex101

I think the logic in this regex speaks for itself, so I will merely pretty-print but not comment it:

^
(
    (
        2(?!5?[6-9])
    |
        1
    |
        (?!0\B)
    )
    \d\d?
    \.?\b
){4}
$

This can be used to shave 2 bytes off the following other answers:

Here is an alternative version that allows leading zeros, but does so consistently (octets may be represented by a maximum of 3 decimal digits):

^((2(?!5?[6-9])|1|0?)\d\d?\.?\b){4}$

Or allow any number of leading zeros:

^(0*(2(?!5?[6-9])|1?)\d\d?\.?\b){4}$


1
\b and \B... it's smart!
mazzy

1
@mazzy Yes, those two really come in handy! I could've used (?!0\d) instead, but I like \B better!
Deadcode

The powershell answer doesn't get shorter with your regexp. I'm sorry. Quotes are needed to convert an array to a string. Try it online!
mazzy

1
The \.?\b saved me a byte on my answer too, thanks!
Neil

1
Saved 3 bytes thx
l4m2

2

Red, 106 bytes

func[s][if error? try[t: load s][return off]if 4 <> length? t[return off]s =
form as-ipv4 t/1 t/2 t/3 t/4]

Try it online!

Returnd true or false

Explanation:

f: func [ s ] [
    if error? try [                  ; checks if the execution of the next block result in an error
        t: load s                    ; loading a string separated by '.' gives a tuple   
    ] [                              ; each part of which must be in the range 0..255
        return off                   ; if there's an error, return 'false' 
    ]
    if 4 <> length? t [              ; if the tuple doesn't have exactly 4 parts
        return off                   ; return 'false'  
    ]
    s = form as-ipv4 t/1 t/2 t/3 t/4 ; is the input equal to its parts converted to an IP adress
]

2

Stax, 14 bytes

∞n·Θ3ª&JH‼∙*~Γ

Run and debug it

Unpacked, ungolfed, and commented, it looks like this.

VB      constant 256
r       [0 .. 255]
'|*     coerce and string-join with "|"; i.e. "0|1|2|3 ... 254|255"
:{      parenthesize to "(0|1|2|3 ... 254|255)"
]4*     make 4-length array of number pattern
.\.*    string join with "\\."; this forms the complete regex
|Q      is the input a complete match for the regex?

Run this one


Surprised to know that you made the language Stax! it is working well.
rv7

Thanks! The space of golfing languages is surprisingly crowded, and I'm not sure if stax can justify its own existence on its merits, but my main goal was just to see if I could do it and maybe learn something. It ended up being more fun than expected.
recursive

2

Python 3, 109 93 bytes

import re
lambda x:bool(re.match(r'^((25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(\.(?!$)|$)){4}$',x))

Explanation

Each octet can be 0 - 255 :

  • starts with 25 and having 0-5 as last digit
  • start with 2, has 0-4 as second digit and any digit at the end
  • starts with 1, and 00 - 99 as rest digits
  • has only 2 digits - 1-9 being the first one and any digit thereafter
  • or just a single digit

An octet can end with a (.) or just end, with the condition that it cannot do both , the negative lookahead (?!$) takes care of this case

Thanks @Zachary for making me realize I can discard spaces (since it is code golf)
Thanks @DLosc for the improvements and making me realize my mistake, its been corrected now.


2
Some explanation for this might help.
Nissa

x: re.match=>x:re.match; , x => ,x, and ) is => )is should save 3 bytes. Also, in the regex, you can use \d for each occurrence of [0-9], and [1]=>1. This seems like a great first post, though!
Zacharý

[1-9][0-9]|[0-9] can become [1-9]\d|\d (per Zacharý's advice), which can become [1-9]?\d. Also, instead of testing re.match(...)is not None, you can do bool(re.match(...)) since match objects are truthy and None is falsey. :)
DLosc

Hmm. Actually, this fails on the test case 1.2.3.4.5 (and also 1.2.3.4., which isn't in the official list of test cases), because it can match a period instead of end-of-string after the fourth number.
DLosc


2

Charcoal, 45 21 bytes

I∧⁼№θ.³¬Φ⪪θ.¬№E²⁵⁶Iλι

Try it online! Link is to verbose version of code. Edit: Saved 24 bytes by porting @Shaggy's Japt answer. Explanation:

    θ                   Input string
   №                    Count occurrences of
     .                  Literal `.`
  ⁼                     Equal to
      ³                 Literal 3
 ∧                      Logical And
       ¬                Logical Not
          θ             Input string
         ⪪              Split on
           .            Literal `.`
        Φ               Filter by
            ¬           Logical Not
               ²⁵⁶      Literal 256
              E         Map over implicit range
                   λ    Map value
                  I     Cast to string
             №          Count occurrences of
                    ι   Filter value
I                       Cast to string
                        Implicitly print

Fails for test cases with negative integers like 123.-50.0.12 or 1.1.1.-80. Everything else seems to work fine. So the <256 check should be in [0,255] instead.
Kevin Cruijssen

@KevinCruijssen Actually the code to filter out invalid characters wasn't working because I forgot to change the variable in the inner loop. Should be fixed now.
Neil

2

Retina, 46 44 bytes

^
.
^(\.(25[0-5]|(2[0-4]|1\d|[1-9])?\d)){4}$

Port of @OlivierGrégoire's Java answer, so make sure to upvote him!
-2 bytes thanks to @Neil.

Try it online.

Explanation:

^
.                           # Prepend a dot "." before the (implicit) input
^...$                       # Check if the entire string matches the following regex
                            # exactly, resulting in 1/0 as truthy/falsey:
 (                          #  Open a capture group
  \.                        #   A dot "."
    (25[0-5]                #   Followed by a number in the range [250,255]
    |(2[0-4]|         ) \d) #   or by a number in the range [200,249]
    |(      |1\d|     ) \d) #   or by a number in the range [100,199]
    |(          |[1-9]) \d) #   or by a number in the range [10,99]
    |(                )?\d) #   or by a number in the range [0,9]
 )                          #  Close capture group
  {4}                       #  This capture group should match 4 times after each other

My attempt (which I didn't post because the question got put on hold at the time) was the same length, but didn't have the \d group optimisation, so you can save two bytes because you don't need the M specification on the last line.
Neil

I managed to get Retina down to 42 bytes by porting the Perl 6 answer but this answer also works in 0.8.2 which my port doesn't.
Neil

2

Jelly, 11 bytes

⁹ḶṾ€ṗ4j€”.ċ

A monadic link accepting a list of characters which yields 1 if it's a valid address and 0 otherwise. Builds a list of all 2564=4294967296 addresses and then counts the number of occurrences of the input therein.

Here's similar @ Try it online! that uses 16 () rather than 256 (), since the method is so inefficient!

How?

⁹ḶṾ€ṗ4j€”.ċ - Link: list of characters, S
⁹           - literal 256
 Ḷ          - lowered range = [0,1,2,...,254,255]
  Ṿ€        - unevaluate €ach = ['0','1',...,['2','5','4'],['2','5','5']]
    ṗ4      - 4th Cartesian power = ALL 256^4 lists of 4 of them
            -               (e.g.: ['0',['2','5','5'],'9',['1','0']])
        ”.  - literal '.' character
      j€    - join for €ach (e.g. ['0','.','2','5','5','.','9','.','1','0'] = "0.255.9.10")
          ċ - count occurrences of right (S) in left (that big list)

Why does the version with 65,536 IPs take 1.8 seconds? o_O
Dennis

2

Retina, 42 41 bytes

~(K`

255*
["^(("|'|]")\.?\b){4}$"L$`
$.`

Try it online! Based on a previous version of @nwellnhof's Perl 6 answer, but 1 byte saved by stealing the \.?\b trick from @Deadcode's answer. Explanation:

K`

Clear the work area.

255*

Insert 255 characters.

["^(("|'|]")\.?\b){4}$"L$`
$.`

Generate the range 0..255 separated with |s, prefixed with ^((, and suffixed with )\.?\b){4}$, thus building the regular expression ^((0|1|...255)\.?\b){4}$.

~(

Evaluate that on the original input.


1

Pip, 25 16 bytes

a~=X,256RL4J"\."

Takes the candidate IP address as a command-line argument. Try it online! or Verify all test cases

Explanation

Regex solution, essentially a port of recursive's Stax answer.

                  a is 1st cmdline arg (implicit)
    ,256          Range(256), i.e. [0 1 2 ... 255]
   X              To regex: creates a regex that matches any item from that list
                  i.e. essentially `(0|1|2|...|255)`
        RL4       Create a list with 4 copies of that regex
           J"\."  Join on this string
 ~=               Regex full-match
a                 against the input

1

JavaScript, 89 bytes

(_,r=`(${[...Array(256).keys()].join`|`})`)=>RegExp(`^${(r+'\\.').repeat(3)+r}$`).test(_)

Try it online!

Create RegExp capture groups from indexes of an array having length 256 for range 0-255 joined with | and followed by escaped . character (^(0|1...|255)\.(0|1...|255)\.(0|1...|255)\.(0|1...|255)$) repeated 3 times closing with joined array followed by $ to match end of string, return true or false result of input passed to RegExp.prototype.test().

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.