IPv4 adresimin eksik dönemlerini düzelt


37

Bazen bir IPv4 adresi yazarken, tüm sayıları doğru buluyorum, ancak bir veya daha fazla dönem yazmayı unuttum. Kırık IPv4 adresimi alan ve eksik dönemlerin olası tüm geçerli yerleşimlerini çıkaran bir program (veya işlev) kullanmak istiyorum.

Giriş

Girdi her zaman geçerli bir IPv4 adresinin dönüşümü olan bir dize olacaktır (aşağıdaki ayrıntılara bakın). Her zaman yalnızca bir veya daha fazla dönem karakterinin ortadan kaldırılmasıyla dönüştürülmüş olacak.

Gönderdiğiniz bu format dışındaki girişleri işlemeniz gerekmez.

Çıktı

Girdiden nokta karakterlerinin girilmesi ile girilen tüm geçerli IPv4 adreslerini temsil eden dizelerin belirli bir sıra veya biçimde olmayan bir koleksiyonu veya listesi.

  • Çıktı, yerel bir liste veya sıralı veya sıralanmamış bir koleksiyon türü olabilir.
  • Alternatif olarak, açık bir şekilde ayrılmış IPv4 adresinin bir dizi dizisi olabilir.
    • Dizginizi sınırlandırmak için tek karakterli bir sınırlayıcı kullanıyorsanız, bu tek karakterli sınırlayıcı olarak noktalara ve rakamlara izin verilmez. Sayıların aksine, sınırlayıcı olarak geçen sürelerin belirsiz olmadığını (her dördüncü periyot zorunlu olarak sınırlayıcı olacağından) fark ediyorum;

IPv4 adres formatı

IPv4 adresleri gerçekten yalnızca dört ikili oktet dizisi olsa da, bu zorluk sınırlı bir noktalı ondalık biçimini kullanır.

  • IPv4 adresi, üç döneme ayrılmış dört ondalık değerdir.
  • Dört değerlerin her biri aralığındaki 0için 255kapsayıcı.
  • Önde gelen sıfırlara herhangi bir sayı değerinde izin verilmez . (Bağımsız bir karakter 0izin herhangi bir başka sayıda sıfır ile başlayan değildir: 052, 00vs.)

Test Kılıfları

Girdi ilk satırda, ikinci satırda çıktı (burada, çevrelenmiş virgülle ayrılmış, virgülle ayrılmış alıntı dizgiler listesi olarak yapılandırılmış [ ], ancak yukarıda belirtilen şekilde herhangi bir makul biçim veya yapı kullanabilirsiniz). Bazı örneklerde, belirli bir kuralın uygulanmasını vurgulamak için üçüncü bir satırda notlar vardır.

192.168.1234
["192.168.1.234", "192.168.12.34", "192.168.123.4"]

192.1681234
["192.16.81.234", "192.168.1.234", "192.168.12.34", "192.168.123.4"]
(Note: 192.1681.2.34 (etc.) is illegal because 1681 is greater than 255)

1921681.234
["19.216.81.234", "192.16.81.234", "192.168.1.234"]

1921681234
["19.216.81.234", "192.16.81.234", "192.168.1.234", "192.168.12.34", "192.168.123.4"]

192.168.1204
["192.168.1.204", "192.168.120.4"]
(Note: 192.168.12.04 is illegal because of leading zero)

192.168.123
["1.92.168.123", "19.2.168.123", "192.1.68.123", "192.16.8.123", "192.168.1.23", "192.168.12.3"]

192.168.256
["192.168.2.56", "192.168.25.6"]
(Note: Any combination that would leave 256 intact is illegal)

120345
["1.20.3.45", "1.20.34.5", "1.203.4.5", "12.0.3.45", "12.0.34.5", "120.3.4.5"]
(Note: 12.03.4.5 (etc.) is illegal due to leading zero.)

012345
["0.1.23.45", "0.1.234.5", "0.12.3.45", "0.12.34.5", "0.123.4.5"]
(Note: the first segment must be 0, because `01` or `012` would be illegal.)

000123
["0.0.0.123"]

(Bu örnekleri el ile yaptım, lütfen bulabildiğiniz herhangi bir hata için beni uyarın.)


çıktı sırası önemli mi?
SİZE

@YOU No: " Bir koleksiyon veya liste, belirli bir düzen veya formatta değil ... "
apsillers

Önde gelen sıfırlara izin verilmez : Bu giriş için de geçerli mi?
Luis Mendo

3
Öyleyse .... "000125" yalnızca bir doğru çözüm getirmeli ... 0.0.0.125?
Keeta

2
@Keeta Bu kesinlikle doğru. (Sadece bir test davası olarak ekledim.)
apsillers

Yanıtlar:


9

Pyth, 24 bayt

f&q4lJcT\.!-J`M256jL\../

Çevrimiçi deneyin

Nasıl çalışır

                      ./Q   all partitions of input
                  jL\.      join each on .
f                           filter for results T such that:
      cT\.                    split T on .
     J                        assign to J
    l                         length
  q4                          equals 4
 &                            … and:
           -J`M256              J minus the list of representations of [0, …, 255]
          !                     is false (empty)

Pyth, 17 bayt, çok yavaş

@FjLL\.,^U256 4./

Uyarı. Koşma. Yaklaşık 553 GiB RAM gerektirir.

Nasıl çalışır

       ,             two-element list of:
        ^U256 4        all four-element lists of [0, …, 255]
               ./Q     all partitions of input
  jLL\.              join each element of both on .
@F                   fold intersection

Güzel! Sadece kendi anlayışım için, "girişin tüm bölümleri" girişi mümkün olan tüm bölümlere ayırmak anlamına geliyor, değil mi? Her bölünme ihtimaliyle yapıp sonra dönemlere ile bölünme yeniden katılma, bu nedenle gibi adayların yükleri ile bitirmek Yani 1.9.2.1.6.8.1.2ve 19.2.1.6.8.1.2vb? (Ama sonra açıkçası tüm geçersiz olanları filtrelenir)
apsillers

@ apsillers Doğru.
Anders Kaseorg

16

C (gcc / linux), 125 121 bayt

i;f(char*a){do{char*y=a,s[99],*x=inet_ntop(2,&i,s,99);for(;*x&&!(*x^*y&&*x^46);++x)y+=*x==*y;*x|*y||puts(s);}while(++i);}

Üzerinde Döngüler tüm olası IPv4 adresleri ve üretilen ip adresi (ancak ana karşılaştırma adresi) ilave noktaların üzerine atlama yazdırmak edip etmemeye karar vermek o özel karşılaştırma yapar. Çok yavaş, ancak makul bir bilgisayarda 1 saat içinde bitmelidir .


Kaldırabilirsiniz i=0;.
16'da

@ReleasingHeliumNuclei Yapamayacağımı düşündüm (bir fonksiyon yeniden kullanılabilir olmalı), ama şimdi fonksiyonun i0'dan sonra tekrar olduğunu
anladım

6

Perl 5, 91 bayt

<>=~/^(([1-9]?|1\d|2[0-4])\d|25[0-5])\.?((?1))\.?((?1))\.?((?1))$(?{print"$1.$3.$4.$5 "})^/

Program, tek bir girişin tek bir satırını bekler ve alanla ayrılmış adayların listesini çıkarır.

açıklama

Program, giriş dizesinden geçerli bir IPv4 adresi oluşturma olasılıkları üzerinde dolaşmak için regex'in geri izleme özelliğini kullanır.

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

İsteğe bağlı IPv4 regex ., burada not hiçbir şey.

(?{print"$1.$3.$4.$5 "})

Yakalama gruplarının içeriğini basan bir kod değerlendirme ifadesi.

^

Maçın başarısız olmasını sağlayın ve geri izlemeyi zorlayın.

Örnek çalışma

$ echo "012345" | perl G89503.pl
0.12.34.5 0.12.3.45 0.1.23.45 0.1.234.5 0.123.4.5

5

JavaScript (ES6), 147 141 135 bayt

f=(s,n=0)=>(a=s.split`.`)[3]?a.every(s=>s==`0`|s[0]>0&s<256)?s+' ':'':[...s].map((_,i)=>i>n?f(s.slice(0,i)+`.`+s.slice(i),i):``).join``
<input placeholder=Input oninput=o.textContent=f(this.value)><div id=o style=font-family:monospace;width:1em>Output

Düzenleme: @ apsillers sayesinde 6 bayt kaydedildi. @ YOU'nın geçerlilik testini kopyalayarak 6 bayt daha kaydedildi.


1-9] | 0 ve [0-9] veya \ d arasında bir fark var mı?
SİZE

@ apsillers Ah evet, kodumun daha önceki bir sürümü .testi atacak bir iz bırakabilir , ancak bu sürümün tamam olduğunu düşünüyorum.
Neil

@YOU önemli bit olduğunu 0bir sahiptir $. (Aynı zamanda bir eksik ^, bu yüzden dikkatimi üzerine çektiğiniz için teşekkür ederiz.)
Neil

@ apsillers Ne yazık ki splicebu şekilde çalışmaz, diziyi değiştirir ve kaldırılan öğeleri döndürür.
Neil

4

Python 3, 232 bayt

import re,itertools as t,ipaddress as k
R=range
i=input()
for d in R(5):
 for p in t.combinations(R(len(i)),d):
  n=i;o=0
  for a in p:n=n[:a+o]+'.'+n[a+o:];o+=1
  try:k.ip_address(n);print(n*(not re.search(r'\D?0\d',n)))
  except:0

Oldukça basit: Her yere periyotlar yerleştirir ve verilen periyotlarla IP adresi geçerliyse yazdırırız. IP adreslerinin geçerliliğini (ab) kullanarak kontrol ederiz ipaddress.ip_address; giriş geçerli bir IP adresi değilse, bir istisna oluşturur. ip_addressZorluk, başa çıkamayan bazı ek kuralları tanımlar (yani, baştaki sıfırlar olamaz), bu yüzden düzenli ifadeli olanları da kontrol eder, sonra yazdırırız.

Her çözümü, rasgele sayıda boş satırla karıştırılmış yeni bir satıra çıkarır.

Örnek çalışma:

$ echo 012345 | python fixip.py
0.1.23.45
0.1.234.5
0.12.3.45
0.12.34.5
0.123.4.5





$ echo 000123 | python fixip.py
0.0.0.123








_

İşte benim eski 248 bayt Python 2 çözümüm. İkinci ve üçüncü girinti seviyeleri sırasıyla \t(ham sekme) ve \t (ham sekme artı boşluk). Bu , Markdown ile gerçekten kötü oynuyor , bu yüzden sekmeler iki boşlukla değiştirildi.

import socket,re,itertools as t
R=range
i=input()
for d in R(5):
 for p in t.combinations(R(len(i)),d):
  n=i;o=0
  for a in p:n=n[:a+o]+'.'+n[a+o:];o+=1
  try:
   socket.inet_aton(n)
   if n.count('.')==3and not re.search(r'\D?0\d',n):print n
  except:0

Tırnaklarla çevrili girişi gerektirir (örn. "123.456.789"). Üretilen her IP adresini yeni bir satıra çıkarır.

@Grawity sayesinde 9 bayt kurtarıldı!


1
Misiniz ipaddress.ip_address()+ manuel kontrol aton daha kısa?
Grawity


2

Python 3, 262 260 bayt

p,l,L,T=set(),-1,len,tuple
while l<L(p):l=L(p);p|={T(z[:i]+(y[:j],y[j:])+z[i+1:])for z in set(p)or[T(input().split("."))]for i,y in enumerate(z)for j in range(1,L(y))}
print(['.'.join(x)for x in p if L(x)==4and all(y=='0'or y[0]!='0'and int(y)<256for y in x)])

Hiçbir kütüphane kullanılmadı, ancak geç ve daha uzun, bazı bariz golf tekniklerini özlüyor olabilirim.

Yine de sonuçlar.

for x in 192.168.1234 192.1681234 1921681.234 1921681234 192.168.1204 192.168.123 192.168.256 120345 012345 000123; do
echo $x | python3 ipv4.py
done;

['192.168.123.4', '192.168.1.234', '192.168.12.34']
['192.16.81.234', '192.168.1.234', '192.168.123.4', '192.168.12.34']
['19.216.81.234', '192.168.1.234', '192.16.81.234']
['19.216.81.234', '192.168.123.4', '192.168.12.34', '192.16.81.234', '192.168.1.234']
['192.168.1.204', '192.168.120.4']
['192.16.8.123', '19.2.168.123', '1.92.168.123', '192.168.1.23', '192.168.12.3', '192.1.68.123']
['192.168.25.6', '192.168.2.56']
['1.20.3.45', '1.203.4.5', '12.0.34.5', '120.3.4.5', '1.20.34.5', '12.0.3.45']
['0.1.23.45', '0.12.3.45', '0.12.34.5', '0.123.4.5', '0.1.234.5']
['0.0.0.123']

1
Geçerlilik sınavınızı kopyalayacağımı ve orfıkra etrafındaki parantezlere ihtiyacınız olup olmadığını merak ettiğimi düşündüm ?
Neil

@Neil, teşekkürler, onlara gerek yoktu.
SİZ
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.