Memperbaiki periode hilang alamat IPv4 saya

37

Kadang-kadang ketika saya mengetik alamat IPv4, saya mendapatkan semua nomor dengan benar, tapi saya lupa mengetik satu atau lebih periode. Saya ingin memiliki program (atau fungsi) yang mengambil alamat IPv4 saya yang rusak dan menampilkan semua kemungkinan penempatan yang valid dari periode yang hilang.

Memasukkan

Input akan selalu berupa string yang merupakan transformasi dari alamat IPv4 yang valid (lihat keterangan di bawah). Itu akan selalu telah ditransformasikan semata-mata oleh penghapusan satu atau lebih karakter periode.

Kiriman Anda tidak perlu menangani input di luar format ini.

Keluaran

Kumpulan atau daftar, tanpa urutan atau format tertentu, dari string yang mewakili semua alamat IPv4 yang valid yang dapat dibuat dari input dengan memasukkan karakter periode ke dalam input.

  • Outputnya mungkin berupa daftar asli-bahasa atau jenis koleksi lain yang dipesan atau tidak.
  • Atau, itu mungkin urutan string alamat IPv4 dibatasi dengan cara yang jelas.
    • Jika Anda menggunakan pembatas satu karakter untuk membatasi string Anda, titik dan digit tidak diperbolehkan sebagai pembatas satu karakter. Saya menyadari bahwa, tidak seperti angka, periode sebagai pembatas tidak ambigu (karena setiap periode keempat akan menjadi pembatas) tetapi demi keterbacaan, saya tidak mengizinkannya.

Format alamat IPv4

Sementara alamat IPv4 sebenarnya hanya urutan empat oktet biner, tantangan ini menggunakan format desimal bertitik terbatas.

  • Alamat IPv4 adalah empat nilai desimal yang dipisahkan oleh tiga periode.
  • Masing-masing dari empat nilai berada di kisaran 0untuk 255, inklusif.
  • Angka nol di depan tidak diizinkan dalam nilai angka apa pun. (Standalone satu karakter 0diperbolehkan; nomor lain dimulai dengan nol adalah tidak: 052, 00, dll)

Uji Kasus

Input ada di baris pertama, output di baris kedua (di sini, disusun sebagai daftar string yang dikutip koma, dipisahkan oleh koma, dikelilingi oleh [ ], tetapi Anda dapat menggunakan format atau struktur yang masuk akal, seperti yang ditentukan di atas). Beberapa contoh memiliki catatan pada baris ketiga untuk menyoroti penerapan aturan tertentu.

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

(Saya membuat contoh ini dengan tangan, jadi tolong beri tahu saya jika ada kesalahan yang Anda temukan.)

apsillers
sumber
Urutan output itu penting?
ANDA
@Anda Tidak: " Koleksi atau daftar, tanpa urutan atau format tertentu ... "
apsillers
Angka nol di depan tidak diperbolehkan : Apakah itu berlaku untuk input juga?
Luis Mendo
3
Jadi .... "000125" seharusnya hanya mengembalikan satu solusi yang benar ... 0.0.0.125?
Keeta
2
@ Keeta Itu benar sekali. (Saya baru saja menambahkannya sebagai test case.)
apsillers

Jawaban:

9

Pyth, 24 byte

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

Cobalah online

Bagaimana itu bekerja

                      ./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 byte, sangat lambat

@FjLL\.,^U256 4./

Peringatan. Jangan lari. Membutuhkan sekitar 553 GiB RAM.

Bagaimana itu bekerja

       ,             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
Anders Kaseorg
sumber
Bagus! Hanya untuk pemahaman saya sendiri, "semua partisi input" berarti semua cara yang mungkin untuk mensegmentasi input, kan? Jadi Anda membuat setiap kemungkinan perpecahan dan kemudian bergabung kembali dengan periode, sehingga Anda berakhir dengan banyak kandidat seperti 1.9.2.1.6.8.1.2dan 19.2.1.6.8.1.2lain - lain? (Tapi kemudian jelas semua yang tidak valid bisa disaring)
apsillers
@apsillers Benar.
Anders Kaseorg
16

C (gcc / linux), 125 121 byte

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

Simpulkan semua alamat IPv4 yang mungkin, dan lakukan perbandingan khusus yang melompati titik-titik tambahan dalam alamat ip yang dihasilkan (tetapi tidak dalam alamat perbandingan utama) untuk memutuskan apakah akan mencetak atau tidak. Sangat lambat, tetapi harus selesai dalam 1 jam pada PC yang wajar .

orlp
sumber
Anda dapat menghapus i=0;.
betseg
@ReleasingHeliumNuclei Saya pikir saya tidak bisa (fungsi harus dapat digunakan kembali), tapi sekarang saya menyadari bahwa setelah fungsi iadalah 0 lagi ...
orlp
6

Perl 5, 91 byte

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

Program ini mengharapkan satu baris dari satu input dan output daftar kandidat yang dibatasi ruang.

Penjelasan

Program ini mengeksploitasi fitur backtracking regex untuk mengulang semua kemungkinan pembentukan alamat IPv4 yang valid dari string input.

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

Regex IPv4 dengan opsional ., tidak ada catatan di sini.

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

Ekspresi evaluasi kode yang mencetak konten dari grup yang menangkap.

^

Buat pertandingan gagal dan paksa mundur.

Contoh dijalankan

$ 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
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
sumber
5

JavaScript (ES6), 147 141 135 byte

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

Sunting: disimpan 6 byte berkat @apsillers. Menyimpan 6 byte lainnya dengan menyalin uji validitas ANDA.

Neil
sumber
apakah ada perbedaan antara [1-9] | 0 dan [0-9] atau \ d ??
ANDA
@apsillers Ah ya, versi kode saya yang lebih lama bisa menghasilkan trailing .yang akan membuang tes, tapi saya pikir versi ini OK.
Neil
@ YOU Yang penting adalah bahwa 0memiliki $. (Ini juga tidak ada ^, jadi terima kasih telah menarik perhatian saya ke sana.)
Neil
@apsillers Sayangnya splicetidak berfungsi seperti itu, ia memodifikasi array dan mengembalikan elemen yang dihapus.
Neil
4

Python 3, 232 byte

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

Cukup sederhana: Kami menempatkan titik di mana-mana dan mencetak jika alamat IP dengan periode yang ditempatkan valid. Kami memeriksa validitas alamat IP dengan (ab) menggunakan ipaddress.ip_address, yang menimbulkan pengecualian jika inputnya bukan alamat IP yang valid. Tantangannya mendefinisikan beberapa aturan tambahan yang ip_addresstidak menangani (yaitu, bahwa tidak ada nol terkemuka), jadi kami memeriksa mereka juga dengan ekspresi reguler, lalu mencetak.

Output setiap solusi pada baris baru, dicampur dengan jumlah baris kosong sewenang-wenang.

Contoh dijalankan:

$ 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








_

Inilah solusi Python 2 248-byte saya yang lebih lama. Level indent kedua dan ketiga adalah \t(tab mentah) dan \t (tab mentah ditambah spasi). Ini memainkan sangat buruk dengan penurunan harga, sehingga tab telah digantikan oleh dua spasi.

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

Membutuhkan input yang dikelilingi dengan tanda kutip (misalnya "123.456.789"). Keluaran setiap alamat IP yang dihasilkan pada baris baru.

Disimpan 9 byte berkat @grawity!

Tembaga
sumber
1
Akan ipaddress.ip_address()lebih pendek dari pada pemeriksaan manual + aton?
grawity
3

Brachylog , 110 byte

:ef:{".",@N.|.}ac:3f:{@n:"."rz:cacb.}a.
,4yeN,?:N:6i.@nMl4,M:{:7&<256}a
~c[A:B]h:@N:Bc.
:ef:{,"0":"9"y:.m?}ac.

Cobalah online!

Biarawati Bocor
sumber
2

Python 3, 262 260 byte

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

Tidak ada perpustakaan yang digunakan, tetapi terlambat dan lebih lama, mungkin saya kehilangan beberapa teknik golf yang jelas.

Bagaimanapun hasilnya.

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']
KAMU
sumber
1
Saya pikir saya akan menyalin tes validitas Anda dan bertanya-tanya apakah Anda memerlukan tanda kurung di sekitar orklausa?
Neil
@ Neil, terima kasih, tidak butuh itu.
ANDA