Corrigir os períodos ausentes do meu endereço IPv4


37

Às vezes, quando digito um endereço IPv4, acerto todos os números, mas esqueço de digitar um ou mais períodos. Eu gostaria de ter um programa (ou função) que aceite meu endereço IPv4 quebrado e produza todas as veiculações válidas possíveis dos períodos ausentes.

Entrada

A entrada sempre será uma sequência que é uma transformação de um endereço IPv4 válido (consulte os detalhes abaixo). Ele sempre será transformado exclusivamente pela eliminação de um ou mais caracteres de ponto final.

Seu envio não precisa manipular entradas fora deste formato.

Saída

Uma coleção ou lista, em nenhuma ordem ou formato específico, de cadeias que representam todos os endereços IPv4 válidos que podem ser criados a partir da entrada pela inserção de caracteres de ponto na entrada.

  • A saída pode ser uma lista nativa do idioma ou outro tipo de coleção ordenada ou não ordenada.
  • Como alternativa, pode ser uma sequência de cadeias de endereços IPv4 delimitada de alguma maneira clara.
    • Se você usar um delimitador de caractere único para delimitar sua sequência, pontos e dígitos não serão permitidos como esse delimitador de caractere único. Percebo que, diferentemente dos números, os períodos como delimitadores não são ambíguos (uma vez que cada quarto período seria necessariamente um delimitador), mas por uma questão de legibilidade, eu o estou desaprovando.

Formato de endereço IPv4

Embora os endereços IPv4 sejam realmente apenas uma sequência de quatro octetos binários, esse desafio usa um formato decimal pontilhado restrito.

  • Um endereço IPv4 é um quatro valores decimais separados por três períodos.
  • Cada um dos quatro valores está no intervalo 0de 255, inclusive.
  • Zeros à esquerda não são permitidos em nenhum valor numérico. (Standalone de um caracter 0é permitido; qualquer outro número começando com um zero não é: 052, 00, etc.)

Casos de teste

A entrada está na primeira linha, a saída na segunda linha (aqui, estruturada como uma lista separada por vírgula de seqüências de caracteres entre aspas, separada por vírgulas, entre elas [ ], mas você pode usar qualquer formato ou estrutura razoável, conforme especificado acima). Alguns exemplos têm anotações em uma terceira linha para destacar a aplicação de uma regra específica.

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

(Eu fiz esses exemplos manualmente, então me avise sobre quaisquer erros que você possa encontrar.)


ordem de saída é importante?
VOCÊ

@YOU No: " Uma coleção ou lista, em nenhuma ordem ou formato específico ... "
apsillers

Zeros à esquerda não são permitidos : isso também se aplica à entrada?
Luis Mendo

3
Então .... "000125" deve retornar apenas uma solução correta ... 0.0.0.125?
Keeta

2
@ Keeta Isso é exatamente correto. (I acabou de adicionar-lo como um caso de teste.)
apsillers

Respostas:


9

Pitão, 24 bytes

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

Experimente online

Como funciona

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

Pitão, 17 bytes, muito lento

@FjLL\.,^U256 4./

Atenção. Não corra. Requer aproximadamente 553 GiB de RAM.

Como funciona

       ,             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

Agradável! Para meu próprio entendimento, "todas as partições de entrada" significam todas as formas possíveis de segmentar a entrada, certo? Então você faz todas as divisões possíveis e depois junta as divisões com pontos, para acabar com vários candidatos como 1.9.2.1.6.8.1.2e 19.2.1.6.8.1.2etc.? (Mas, então, obviamente, todos os inválidos são filtrados para fora)
apsillers

@apsillers Correto.
Anders Kaseorg 11/08/16

16

C (gcc / linux), 125 121 bytes

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

Faz um loop em todos os endereços IPv4 possíveis e faz uma comparação personalizada que pula pontos extras no endereço IP gerado (mas não no endereço de comparação principal) para decidir se deseja imprimir ou não. Muito lento, mas deve terminar dentro de 1 hora em um PC razoável .


Você pode remover o i=0;.
precisa saber é

@ReleasingHeliumNuclei eu pensei que eu não poderia (a função deve ser re-utilizáveis), mas agora eu percebo que após a função ié 0 novamente ...
orlp

6

Perl 5, 91 bytes

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

O programa espera uma única linha de uma única entrada e gera uma lista de candidatos delimitada por espaço.

Explicação

O programa explora o recurso de retorno do regex para fazer um loop em todas as possibilidades de formar um endereço IPv4 válido a partir da sequência de entrada.

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

O regex IPv4 com opcional ., nada de importante aqui.

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

Uma expressão de avaliação de código que imprime o conteúdo dos grupos de captura.

^

Faça a partida falhar e force o retorno.

Exemplo de execução

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

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

Editar: salvou 6 bytes graças a @apsillers. Economizou outros 6 bytes copiando o teste de validade de @ YOU.


existe uma diferença entre [1-9] | 0 e [0-9] ou \ d ??
VOCÊ

@apsillers Ah sim, uma versão anterior do meu código poderia gerar um trailing .que lançaria o teste, mas acho que esta versão está correta.
Neil

@YOU O pouco mais importante é que ele 0tem um $. (Também está faltando um ^, por isso obrigado por chamar minha atenção para ele.)
Neil

@apsillers Infelizmente splice, não funciona assim, modifica a matriz e retorna todos os elementos removidos.
Neil

4

Python 3, 232 bytes

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

Bem simples: colocamos períodos em todos os lugares e imprimimos se o endereço IP com os períodos colocados é válido. Verificamos a validade dos endereços IP usando (ab) usando ipaddress.ip_address, o que gera uma exceção se a entrada não for um endereço IP válido. O desafio define algumas regras adicionais que ip_addressnão tratam (ou seja, que não pode haver zeros à esquerda), portanto, verificamos essas também com uma expressão regular e depois imprimimos.

Produz cada solução em uma nova linha, combinada com um número arbitrário de linhas em branco.

Exemplo de execução:

$ 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








_

Aqui está minha solução Python 2 mais antiga de 248 bytes. Os segundo e terceiro níveis de recuo são \t(guia bruta) e \t (guia bruta mais espaço), respectivamente. Isso funciona muito mal com o Markdown, então as guias foram substituídas por dois espaços.

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

Requer a entrada entre aspas (por exemplo "123.456.789"). Produz cada endereço IP gerado em uma nova linha.

Guardado 9 bytes graças a @grawity!


1
Seria ipaddress.ip_address()mais curto que o aton + verificação manual?
grawity


2

Python 3, 262 260 bytes

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

Nenhuma biblioteca usada, mas tarde e mais, pode estar faltando algumas técnicas óbvias de golfe.

Resultados de qualquer maneira.

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
Pensei em copiar seu teste de validade e me perguntei se você precisa dos parênteses em torno da orcláusula.
Neil

@ Neil, obrigado, não precisava disso.
VOCÊ
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.