Khắc phục các khoảng thời gian thiếu địa chỉ IPv4 của tôi


37

Đôi khi, khi tôi gõ một địa chỉ IPv4, tôi nhận được tất cả các số đúng, nhưng tôi quên gõ một hoặc nhiều dấu chấm. Tôi muốn có một chương trình (hoặc chức năng) lấy địa chỉ IPv4 bị hỏng của tôi và xuất ra tất cả các vị trí hợp lệ có thể có của các giai đoạn bị thiếu.

Đầu vào

Đầu vào sẽ luôn là một chuỗi chuyển đổi địa chỉ IPv4 hợp lệ (xem chi tiết bên dưới). Nó sẽ luôn luôn được chuyển đổi chỉ bằng cách loại bỏ một hoặc nhiều ký tự thời kỳ.

Bạn gửi không cần xử lý đầu vào bên ngoài định dạng này.

Đầu ra

Một bộ sưu tập hoặc danh sách, không theo thứ tự hoặc định dạng cụ thể, của các chuỗi đại diện cho tất cả các địa chỉ IPv4 hợp lệ có thể được tạo từ đầu vào bằng cách chèn các ký tự dấu chấm vào đầu vào.

  • Đầu ra có thể là một danh sách gốc ngôn ngữ hoặc loại bộ sưu tập có thứ tự hoặc không có thứ tự khác.
  • Ngoài ra, nó có thể là một chuỗi chuỗi địa chỉ IPv4 được phân tách theo một cách rõ ràng.
    • Nếu bạn sử dụng một dấu phân cách một ký tự để phân định chuỗi của bạn, dấu chấm và chữ số không được phép làm dấu phân cách một ký tự đó. Tôi nhận ra rằng, không giống như các con số, các giai đoạn như các dấu phân cách không mơ hồ (vì mỗi giai đoạn thứ tư nhất thiết phải là một dấu phân cách) nhưng vì mục đích dễ đọc, tôi không đồng ý.

Định dạng địa chỉ IPv4

Mặc dù địa chỉ IPv4 thực sự chỉ là một chuỗi gồm bốn octet nhị phân, thử thách này sử dụng định dạng thập phân rải rác bị hạn chế.

  • Địa chỉ IPv4 là bốn giá trị thập phân được phân tách bằng ba dấu chấm.
  • Mỗi phòng trong số bốn giá trị nằm trong khoảng 0đến 255, bao gồm.
  • Các số 0 đứng đầu không được phép trong bất kỳ giá trị số nào. (Độc lập một ký tự 0được phép; bất kỳ số khác bắt đầu với một số không không phải là: 052, 00, vv)

Các trường hợp thử nghiệm

Đầu vào nằm trên dòng đầu tiên, đầu ra trên dòng thứ hai (ở đây, được cấu trúc như một danh sách các chuỗi được trích dẫn bằng dấu phẩy, được phân tách bằng dấu phẩy, được bao quanh bởi [ ], nhưng bạn có thể sử dụng bất kỳ định dạng hoặc cấu trúc hợp lý nào, như được chỉ định ở trên). Một số ví dụ có ghi chú trên dòng thứ ba để làm nổi bật ứng dụng của một quy tắc cụ thể.

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

(Tôi đã thực hiện các ví dụ này bằng tay, vì vậy vui lòng cảnh báo tôi về bất kỳ sai lầm nào bạn có thể tìm thấy.)


thứ tự đầu ra là vấn đề?
BẠN

@YOU Không: " Một bộ sưu tập hoặc danh sách, không theo thứ tự hoặc định dạng cụ thể ... "
apsillers

Các số 0 đứng đầu không được phép : Điều đó cũng áp dụng cho đầu vào phải không?
Luis Mendo

3
Vậy .... "000125" chỉ nên trả về một giải pháp đúng ... 0.0.0.125?
Keeta

2
@Keeta Điều đó hoàn toàn chính xác. (Tôi vừa thêm nó dưới dạng thử nghiệm.)
apsillers

Câu trả lời:


9

Bình thường, 24 byte

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

Dùng thử trực tuyến

Làm thế nào nó hoạt động

                      ./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, rất chậm

@FjLL\.,^U256 4./

Cảnh báo. Đừng chạy. Yêu cầu khoảng 553 GiB RAM.

Làm thế nào nó hoạt động

       ,             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

Tốt đẹp! Theo hiểu biết của riêng tôi, "tất cả các phân vùng đầu vào" có nghĩa là tất cả các cách có thể để phân đoạn đầu vào, phải không? Vì vậy, bạn thực hiện mọi phân tách có thể và sau đó tham gia lại các phân chia với các khoảng thời gian, vì vậy bạn kết thúc với vô số ứng cử viên như 1.9.2.1.6.8.1.219.2.1.6.8.1.2vv? (Nhưng sau đó rõ ràng là tất cả những cái không hợp lệ được lọc ra)
apsillers

@apsillers Đúng.
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);}

Vòng lặp trên tất cả các địa chỉ IPv4 có thể và thực hiện so sánh tùy chỉnh bỏ qua các dấu chấm thừa trong địa chỉ IP được tạo (nhưng không phải trong địa chỉ so sánh chính) để quyết định có in hay không. Rất chậm, nhưng sẽ hoàn thành trong vòng 1 giờ trên một PC hợp lý .


Bạn có thể loại bỏ i=0;.
betseg

@ReleaseHeliumNuclei Tôi nghĩ rằng tôi không thể (một chức năng phải được sử dụng lại), nhưng bây giờ tôi nhận ra rằng sau khi chức năng itrở lại 0 ...
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 "})^/

Chương trình mong đợi một dòng duy nhất của một danh sách các ứng cử viên được phân tách không gian đầu vào và đầu ra.

Giải trình

Chương trình khai thác tính năng quay lui của regex để lặp lại tất cả các khả năng hình thành địa chỉ IPv4 hợp lệ từ chuỗi đầu vào.

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

Regex IPv4 với tùy chọn ., không có gì đáng chú ý ở đây.

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

Một biểu thức đánh giá mã in ra nội dung của các nhóm bắt giữ.

^

Làm cho trận đấu thất bại và buộc quay lại.

Chạy ví dụ

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

Chỉnh sửa: đã lưu 6 byte nhờ @apsillers. Đã lưu thêm 6 byte bằng cách sao chép kiểm tra tính hợp lệ của @ YOU.


có sự khác biệt giữa [1-9] | 0 và [0-9] hay \ d ??
BẠN

@apsillers À đúng rồi, một phiên bản trước đó của mã của tôi có thể tạo ra một dấu vết .sẽ ném thử nghiệm, nhưng tôi nghĩ phiên bản này vẫn ổn.
Neil

@YOU Một chút quan trọng là 0có a $. (Nó cũng thiếu một cái ^, vì vậy cảm ơn vì đã thu hút sự chú ý của tôi vào nó.)
Neil

@apsillers Đáng buồn thay, splicenó không hoạt động như vậy, nó sửa đổi mảng và trả về bất kỳ phần tử bị loại bỏ nào.
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

Khá đơn giản: Chúng tôi đặt dấu chấm ở mọi nơi và in nếu địa chỉ IP có dấu chấm được đặt là hợp lệ. Chúng tôi kiểm tra tính hợp lệ của các địa chỉ IP bằng cách (ab) sử dụng ipaddress.ip_address, điều này sẽ phát sinh một ngoại lệ nếu đầu vào không phải là địa chỉ IP hợp lệ. Thách thức xác định một số quy tắc bổ sung ip_addresskhông xử lý (cụ thể là không thể có các số 0 đứng đầu), vì vậy chúng tôi kiểm tra các quy tắc đó bằng một biểu thức thông thường, sau đó in.

Xuất ra mỗi giải pháp trên một dòng mới, trộn với một số dòng trống tùy ý.

Chạy ví dụ:

$ 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








_

Đây là giải pháp Python 2 cũ hơn 248 byte của tôi. Cấp độ thụt thứ hai và thứ ba là\t (tab thô) và \t (tab thô cộng với không gian). Điều này thực sự rất tệ với Markdown, vì vậy các tab đã được thay thế bằng hai khoảng trắng.

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

Yêu cầu đầu vào được bao quanh với dấu ngoặc kép (ví dụ "123.456.789"). Xuất ra từng địa chỉ IP được tạo trên một dòng mới.

Đã lưu 9 byte nhờ @grawity!


1
Sẽ ipaddress.ip_address()ngắn hơn aton + kiểm tra thủ công?
grawity


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

Không có thư viện được sử dụng, nhưng muộn và lâu hơn, có thể tôi đang thiếu một số kỹ thuật chơi gôn rõ ràng.

Kết quả nào.

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
Tôi nghĩ tôi sẽ sao chép bài kiểm tra tính hợp lệ của bạn và tự hỏi liệu bạn có cần dấu ngoặc đơn xung quanh ormệnh đề không?
Neil

@Neil, cảm ơn, không cần những thứ đó.
BẠN
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.