Всесвітній день IPv6 2014 року


22

Щоб відзначити річницю Всесвітнього дня IPv6 , Інтернет-суспільство опублікувало кампанію з вимкнення IPv4 6 червня 2014 року на один день .


Адреси IPv6 можуть бути представлені у довгому вигляді як вісім 16-бітних шестигранних значень, розділених двокрапкою. Залежно від адреси, вони також можуть бути скорочені, як описано в пункті 2 розділу 2.2 Текстове представлення адрес RFC 3513 :

Для полегшення запису адрес, що містять нульові біти, є спеціальний синтаксис для стиснення нулів. Використання "::" вказує на одну або кілька груп з 16 біт нулів. "::" може відображатися лише один раз в адресі. "::" також може використовуватися для стиснення провідних або кінцевих нулів у адреси.

  • Записи на цей виклик буде програми , які приймають рівно один IPv6 - адреса , відформатований в довгій або укороченою форматі, і буде відображати один і той же адресу в обох довгих і коротких форматів, в такому порядку.

  • Вхід може надходити з аргументів командного рядка, STDIN або будь-якого іншого джерела вводу, який відповідає вашому вибору мови.

  • Бібліотеки чи утиліти, спеціально для розбору IPv6-адрес, заборонені (наприклад, inet_ {ntop, pton} () ).

  • Якщо вхідна адреса недійсна, вихід буде порожнім (або подається якесь відповідне повідомлення про помилку, що вказує, що адреса недійсна )

  • У випадках, коли ::відбувається вкорочення, за вказаною адресою може відбутися лише одна операція скорочення. Якщо для даної адреси є кілька потенційних операцій скорочення, слід використовувати операцію, яка дає загальну найкоротшу адресу. Якщо в цьому плані є зв'язання, буде застосована перша операція. Це проілюстровано в прикладах нижче.

  • Стандартні лазівки, яких слід уникати

Приклади:

Input                         Output

1080:0:0:0:8:800:200C:417A    1080:0:0:0:8:800:200C:417A
                              1080::8:800:200C:417A

FF01::101                     FF01:0:0:0:0:0:0:101
                              FF01::101

0:0:0:0:0:0:0:1               0:0:0:0:0:0:0:1
                              ::1

::                            0:0:0:0:0:0:0:0
                              ::

1:0:0:2:0:0:0:3               1:0:0:2:0:0:0:3
                              1:0:0:2::3

1:0:0:8:8:0:0:3               1:0:0:8:8:0:0:3
                              1::8:8:0:0:3

1:2:3:4:5:6:7:8               1:2:3:4:5:6:7:8
                              1:2:3:4:5:6:7:8

ABCD:1234                     <Invalid address format - no output>

ABCDE::1234                   <Invalid address format - no output>

1:2:3:4:5:6:7:8:9             <Invalid address format - no output>

:::1                          <Invalid address format - no output>

codegolf puzzle               <Invalid address format - no output>

Це , тому найкоротша відповідь у байтах 6 червня 2014 року буде прийнята як переможець.


Скажіть, вхід є 1:0:0:2:2::3. Чи буде скорочений вихід ідентичний тому чи 1::2:2:0:0:3? Те саме для неоптимально скороченого введення.
Мартін Ендер

@ m.buettner У цьому випадку я дозволю вам вибрати будь-який.
Цифрова травма

Чи 1::2:0:0:0:3можливий вклад?
користувач12205


2
Я думаю, що це єдиний спосіб, коли хтось змусить мене навчатись ipv6. +1
Непрохідність

Відповіді:


4

JavaScript (ES6) - 198 , 183 , 180 , 188 , 187 байт

f=s=>/^(:[\da-f]{1,4}){8}$/i.test(':'+(s=s[r='replace'](d='::',':0'.repeat((n=8-s.split(/:+/).length%9)||1)+':')[r](/^:0|0:$/g,n?'0:0':0)))&&[s,s[r](/(\b0(:0)*)(?!.*\1:0)/,d)[r](/::+/,d)]

І, трохи довша, інтерактивна версія з деякими спливаючими вікнами (203 байти):

/^(:[\da-f]{1,4}){8}$/i.test(':'+(s=(s=prompt())[r='replace'](d='::',':0'.repeat((n=8-s.split(/:+/).length%9)||1)+':')[r](/^:0|0:$/g,n?'0:0':0)))&&alert(s+'\n'+s[r](/(\b0(:0)*)(?!.*\1:0)/,d)[r](/::+/,d))

Безголівки:

function ipv6(str) {
    "use strict";
    var zeros = 8 - str.split(/:+/).length % 9

        ,longIP = str
            .replace('::', ':0'.repeat(zeros || 1) + ':')
            .replace(/^:0|0:$/g, zeros ? '0:0' : '0')

        ,shortIP = longIP
            .replace(/(\b0(:0)*)(?!.*\1:0)/,':')
            .replace(/::+/,'::');

    return /^(:[\da-f]{1,4}){8}$/i.test(':'+longIP) && [longIP, shortIP];
}

Пояснення:

Для обчислення довгої версії адреси IPv6:

8 - str.split(/:+/).length % 9- обчисліть, скільки нулів нам потрібно вставити. Їх 8 - кількість шестигранних значень. Тут% 9 є охоронним, тому це ніколи не буде від’ємним числом.

replace('::', ':0'.repeat(zeros || 1) + ':')- замініть "::" нулями, розділеними двокрапкою. Якщо немає нулів для додавання, все одно додається одна, щоб адреса не була дійсною в підсумку

replace(/^:0|0:$/g, zeros ? '0:0' : '0')- це стосується особливого випадку, коли адреса починається або закінчується символом "::", оскільки splitфункція додає 1 до числа шістнадцяткових значень (:: 1 -> ["", "1"])

Це воно! Тепер давайте обчислимо коротку форму:

replace(/(\b0(:0)*)(?!.*\1:0)/,':') - замініть найдовший ряд нулів двокрапкою (не важливо, скільки).

replace(/::+/,'::') - видаліть зайві колонки, якщо такі є

return /^(:[\da-f]{1,4}){8}$/i.test(':'+longIP) && [longIP, shortIP];- перевірити, чи довга версія дійсна IPv6, і повернути обидві версії або falseякщо тест не вдався.

Тести на Firefox:

>>> f('1080:0:0:0:8:800:200C:417A')
["1080:0:0:0:8:800:200C:417A", "1080::8:800:200C:417A"]
>>> f('FF01::101')
["FF01:0:0:0:0:0:0:101", "FF01::101"]
>>> f('0:0:0:0:0:0:0:1')
["0:0:0:0:0:0:0:1", "::1"]
>>> f('::')
["0:0:0:0:0:0:0:0", "::"]
>>> f('1:0:0:2:0:0:0:3')
["1:0:0:2:0:0:0:3", "1:0:0:2::3"]
>>> f('1:0:0:8:8:0:0:3')
["1:0:0:8:8:0:0:3", "1::8:8:0:0:3"]
>>> f('1:2:3:4:5:6:7:8')
["1:2:3:4:5:6:7:8", "1:2:3:4:5:6:7:8"]
>>> f('ABCD:1234')
false
>>> f('ABCDE::1234')
false
>>> f('1:2:3:4:5:6:7:8:9')
false
>>> f(':::1')
false
>>> f('1:2:3:4::a:b:c:d')
false
>>> f('codegolf puzzle')
false

Так набагато краще, ніж моя! Просто потрібна певна корекція, щоб обробляти такі входи :: 1 :,: 1 ::
edc65

Цей визнаний недійсним1:2:3:4::a:b:c:d
kernigh

6

Javascript (E6) 246 305 284 292 319

Сильно переглянута Спеціальна справа для :: спеціально оброблюваної фази стискання дозволяє уникнути циклу for (але дійсно не дуже коротший). Я впевнений, що остаточний етап стискання може бути коротшим. Не так чи інакше

F=i=>(c=':',d=c+c,z=':0'.repeat(9-i.split(c,9).length)+c,i=i==d?0+z+0:i[R='replace'](/^::/,0+z)[R](/::$/,z+0)[R](d,z>c?z:d),/^(:[\da-f]{1,4}){8}:$/i.test(k=c+i+c)&&[i,k[R]((k.match(/:(0:)+/g)||[]).sort().pop(),d)[R](/^:([^:])|([^:]):$/g,'$1$2')])

Завдяки nderscore

Як програма

Введення та виведення за допомогою js спливаючого вікна, в основному: p=prompt,p(F(p())) Перезапис із спливаючим вікном та без визначення функції, кількість знаків має бути менше 260

Унгольф і трохи прокоментував

F = i => (
  c = ':',
  d = c+c,
  z = ':0'.repeat(9-i.split(c,9).length) + c, 
  i = i == d ? 0+z+0 /* special case '::' */
    : i.replace(/^::/,0+z) /* special case '::...' */
       .replace(/::$/,z+0) /* special case '...::' */
       .replace(d, z > c ? z : d), /* here, if z==c, not valid: too much colons */
  /^(:[\da-f]{1,4}){8}:$/i.test(k = c+i+c) /* Check if valid */
  && [
   i, 
   k.replace((k.match(/:(0:)+/g)||[]).sort().pop(),d) /* find longest 0: sequence and replace it */
    .replace(/^:([^:])|([^:]):$/g,'$1$2') /* cut leading and trailing colons */
  ]
)

Тест в консолі

i=['1080:0:0:0:8:800:200C:417A'
, '::1:2:3:4:5:6:7', '1:2:3:4:5:6:7::'
, '1:2:3:4::5:6:7:8'
, ':1:2:3:4:5:6:7', '1:2:3:4:5:6:7:'
, 'FF01::101', '0:0:0:0:0:0:0:1'
, '::', '1::', '::1', ':::1', '1:::'
, '1:0:0:2:0:0:0:3', '1:0:0:0:2:0:0:3', '1::8:0:0:0:3'
, '1:2:3:4:5:6:7:8'
, 'ABCD:1234', 'ABCDE::1234', ':::', '::::::::::'
, '1:2:3:4:5:6:7:8:9', '::::1', 'codegolf puzzle'];
i.map(x=>x+' => '+F(x)).join('\n')

Тестовий вихід

"1080:0:0:0:8:800:200C:417A => 1080:0:0:0:8:800:200C:417A,1080::8:800:200C:417A
::1:2:3:4:5:6:7 => 0:1:2:3:4:5:6:7,::1:2:3:4:5:6:7
1:2:3:4:5:6:7:: => 1:2:3:4:5:6:7:0,1:2:3:4:5:6:7::
1:2:3:4::5:6:7:8 => false
:1:2:3:4:5:6:7 => false
1:2:3:4:5:6:7: => false
FF01::101 => FF01:0:0:0:0:0:0:101,FF01::101
0:0:0:0:0:0:0:1 => 0:0:0:0:0:0:0:1,::1
:: => 0:0:0:0:0:0:0:0,::
1:: => 1:0:0:0:0:0:0:0,1::
::1 => 0:0:0:0:0:0:0:1,::1
:::1 => false
1::: => false
1:0:0:2:0:0:0:3 => 1:0:0:2:0:0:0:3,1:0:0:2::3
1:0:0:0:2:0:0:3 => 1:0:0:0:2:0:0:3,1::2:0:0:3
1::8:0:0:0:3 => 1:0:0:8:0:0:0:3,1:0:0:8::3
1:2:3:4:5:6:7:8 => 1:2:3:4:5:6:7:8,1:2:3:4:5:6:7:8
ABCD:1234 => false
ABCDE::1234 => false
::: => false
:::::::::: => false
1:2:3:4:5:6:7:8:9 => false
::::1 => false
codegolf puzzle => false"   

Я б швидше програму, ніж функцію. Я не знаю JavaScript досить добре, щоб знати, чи можливо це.
Цифрова травма

@nderscore На жаль - помилка друку. Виправлено у новому коментарі.
Цифрова травма

Це може бути перетворено в програму, взявши вклад з prompt(). Ось кілька оптимізацій, які знижують його до 290: pastie.org/private/3ccpinzqrvvliu9nkccyg
nderscore

@nderscore: thx, перша заміна не працює для input = '::', все одно чудова робота!
edc65

@ edc65 Я знайшов виправлення для цієї заміни :) pastie.org/private/kee0sdvjez0vfcmlvaxu8q
nderscore

4

Perl - 204 176 190 191 197

(202 символи + 2 для -pпрапора)

$_=uc;(9-split/:/)||/^:|:$/||last;s/^::/0::/;s/::$/::0/;s|::|':0'x(9-split/:/).':'|e;/::|^:|:$|\w{5}|[^A-F0-:].*\n/||(8-split/:/)and last;s/\b0*(?!\b)//g;print;s/\b((0:)*0)\b(?!.*\1:0\b)/::/;s/::::?/::/

Приклад:

$ perl -p ipv6.pl <<< 1:0:2:0::3
1:0:2:0:0:0:0:3
1:0:2::3
$ perl -p ipv6.pl <<< somethinginvalid
$ perl -p ipv6.pl <<< 1:2:0:4:0:6::8
1:2:0:4:0:6:0:8
1:2::4:0:6:0:8

Пояснення:

# -p reads a line from stdin and stores in $_
#
# Convert to uppercase
$_ = uc;

# Detect the annoying case @kernigh pointed out
(9 - split /:/) || /^:|:$/ || last;

# Fix :: hanging on the beginning or the end of the string
s/^::/0::/;
s/::$/::0/;

# Replace :: with the appropriate number of 0 groups
s|::|':0' x (9 - split /:/) . ':'|e;

# Silently exit if found an extra ::, a hanging :, a 5-char group, an invalid
# character, or there's not 8 groups
/::|^:|:$|\w{5}|[^A-F0-:].*\n/ || (8 - split /:/) and last;

# Remove leading zeros from groups
s/\b0*(?!\b)//g;

# Output the ungolfed form
print;

# Find the longest sequence of 0 groups (a sequence not followed by something
# and a longer sequence) and replace with ::
# This doesn't replace the colons around the sequence because those are optional
# thus we are left with 4 or 3 colons in a row
s/\b((0:)*0)\b(?!.*\1:0\b)/::/;

# Fix the colons after previous transformation
s/::::?/::/

# -p then prints the golfed form of the address

1
"Помер у ipv6.pl рядок 1, <> рядок 1" . Про це йшлося у коментарях до запитання. Якщо є повідомлення, повинно бути зрозуміло, що це через недійсне повідомлення. Я намагався уточнити це в питанні. Інакше добре виглядає!
Цифрова травма

1
@DigitalTrauma Змінено dieна безшумний вихід.
mniip

1
Жук? Ця програма приймає недійсну адресу 1:2:3:4::a:b:c:d. Це дратує особливий випадок, тому що більшість адреси вісім-ободової кишки є недійсним, але ::2:3:4:a:b:c:dі 1:2:3:4:a:b:c::є дійсними.
kernigh

3

sed, 276

У мене 275 байт в ipshorten.sed, плюс 1 байт для -rпереключення в, sed -rfщоб використовувати розширені регулярні вирази. Я використовував OpenBSD sed (1) .

Використання: echo ::2:3:4:a:b:c:d | sed -rf ipshorten.sed

s/^/:/
/^(:[0-9A-Fa-f]{0,4})*$/!d
s/:0*([^:])/:\1/g
s/://
s/::/:=/
s/(.:=)(.)/\10:\2/
s/^:=/0&/
s/=$/&0/
:E
/(.*:){7}/!{/=/!d
s//=0:/
bE
}
s/=//
/^:|::|:$|(.*:){8}/d
p
s/.*/:&:/
s/:((0:)+)/:<\1>/g
:C
s/0:>/>0:/g
/<0/{s/<>//g
bC
}
s/<>(0:)+/:/
s/<>//g
/^::/!s/://
/::$/!s/:$//

Я використовую 22 регулярні вирази, оскільки sed не може порівнювати числа або створювати масиви. Для кожного рядка введення sed виконує команди та друкує рядок. Під час тестування я помістив у файл декілька рядків передбачуваних IP-адрес і передав цей файл sed. Посилання на розширені регулярні вирази знаходиться у re_format (7) .

  1. s/^/:/додає додаткову двокрапку на початок рядка. Я використовую цю додаткову кишку для гольфу наступні дві команди.
  2. /^(:[0-9A-Fa-f]{0,4})*$/!dперевіряє, чи відповідає вся лінія нульової чи більше груп товстих кольорів, а за ними - нуль-чотири шістнадцяткових цифр !заперечує чек, тому dвидаляє рядки з занадто великими шістнадцятковими числами або з недійсними символами. При dвидаленні рядка sed не виконує більше команд у цьому рядку.
  3. s/:0*([^:])/:\1/gвидаляє провідні 0 з кожного числа. Це зміниться :0000:0000:на :0:0:. Я повинен це зробити, тому що мій цикл скорочення працює лише з одноцифровими 0.
  4. s/://видаляє зайву кишку. Вона видаляє лише першу кишку.
  5. s/::/:=/змінює перший ::на :=. Це так , пізні команди можуть збігатися , =а не ::, і так =не рахується двокрапкою. Якщо немає ::, ця заміна благополучно нічого не робить.
    • Тепер ::потрібно зробити хоча б один 0, але є три різні випадки для розміщення цього 0.
  6. s/(.:=)(.)/\10:\2/це перший випадок. Якщо ::був між двома іншими символами, то :=стає :=0:. Це єдиний випадок, який додає двокрапку.
  7. s/^:=/0&/є другим випадком. Якщо ::було на початку рядка, тоді поставте 0.
  8. s/=$/&0/третій випадок для ::кінця рядка.
  9. :E - мітка для циклу розширення.
  10. /(.*:){7}/!{/=/!dпочинається умовний блок, якщо лінія має менше 7 точок. /=/!dвидаляє лінії, у яких не було ::і не вистачає товстих кольорів.
  11. s//=0:/додає одну двокрапку. Порожня //повторює останній регулярний вираз, тож це насправді s/=/=0:/.
  12. bEгілки, щоб :Eпродовжити петлю.
  13. }закриває блок. Зараз у лінійці принаймні сім колонок.
  14. s/=//видаляє =.
  15. /^:|::|:$|(.*:){8}/d- це остаточна перевірка після розширення. Він видаляє лінії з провідною двокрапкою, додатковою, ::яка не була розширена, зворотною двокрапкою або вісьмома або більше двокрапками.
  16. p друкує рядок, який є IP-адресою у довгій формі.
  17. s/.*/:&:/ загортає адресу в додаткові колонки.
    • Наступне завдання - знайти найдовшу групу 0, як :0:0:0:, наприклад , та укласти її ::.
  18. s/:((0:)+)/:<\1>/gз'їдає кожну групу 0-х, так :0:0:0:би стало :<0:0:0:>.
  19. :C - мітка для петлі скорочення.
  20. s/0:>/>0:/gрухається по одному 0 з кожного рота, так :<0:0:0:>би сталося :<0:0:>0:.
  21. /<0/{s/<>//gвідкриває умовний блок, якщо будь-який рот не порожній. s/<>//gвидаляє всі порожні роти, оскільки ці групи занадто короткі.
  22. bC продовжує цикл скорочення.
  23. }закриває блок. Тепер будь-який рот порожній і позначає найдовшу групу 0.
  24. s/<>(0:)+/:/контракти найдовші групи, так :<>0:0:0:би сталося ::. У краватці він вибирає порожній рот зліва.
  25. s/<>//g видаляє будь-які інші порожні роти.
  26. /^::/!s/://видаляє першу зайву кишку, якщо вона не є частиною ::.
  27. /::$/!s/:$//робить це для останньої додаткової кишки. Потім sed друкує IP-адресу в короткій формі.

1

Пітон 3: 387 символів

Навіть працює з неправильно скороченим входом.

$ echo '1::2:0:0:0:3' | python3 ipv6.py 
1:0:0:2:0:0:0:3
1:0:0:2::3

Подвійний заміни в ':::'с '::'Відчувається дуже погано , але не впевнений , як чисто угоди з найдовшою рядки 0, коли вона упреться один або обидва кінці.

c=':'
p=print
try:
 B=[int(x,16)if x else''for x in input().split(c)];L=len(B)
 if any(B)-1:B=[''];L=1
 if L!=8:s=B.index('');B[s:s+1]=[0]*(9-L)
 for b in B:assert-1<b<2**16
 H=[format(x,'X')for x in B];o=c.join(H);p(o);n=''.join(str(h=='0')[0]for h in H)
 for i in range(8,0,-1):
  s=n.find('T'*i)
  if s>=0:H[s:s+i]=[c*2];p(c.join(H).replace(c*3,c*2).replace(c*3,c*2));q
 p(o)
except:0

Замінити фінал passз , raiseщоб побачити , як це збій захисту від некоректного введення.

$ cat ipv6-test.sh 
echo '1080:0:0:0:8:800:200C:417A' | python3 ipv6.py
echo '1:2:3:4:5:6:7:8' | python3 ipv6.py
echo 'FF01::101' | python3 ipv6.py
echo '0:0:0:0:0:0:0:1' | python3 ipv6.py
echo '0:0:0:0:1:0:0:0' | python3 ipv6.py
echo '1:0:0:0:0:0:0:0' | python3 ipv6.py
echo '::' | python3 ipv6.py
echo '1:0:0:2:0:0:0:3' | python3 ipv6.py
echo '1::2:0:0:0:3' | python3 ipv6.py
echo '1:0:0:8:8:0:0:3' | python3 ipv6.py
echo 'ABCD:1234' | python3 ipv6.py
echo 'ABCDE::1234' | python3 ipv6.py
echo '1:2:3:4:5:6:7:8:9' | python3 ipv6.py
echo ':::1' | python3 ipv6.py
echo 'codegolf puzzle' | python3 ipv6.py
$ ./ipv6-test.sh 
1080:0:0:0:8:800:200C:417A
1080::8:800:200C:417A

1:2:3:4:5:6:7:8
1:2:3:4:5:6:7:8

FF01:0:0:0:0:0:0:101
FF01::101

0:0:0:0:0:0:0:1
::1

0:0:0:0:1:0:0:0
::1:0:0:0

1:0:0:0:0:0:0:0
1::


0:0:0:0:0:0:0:0
::

1:0:0:2:0:0:0:3
1:0:0:2::3

1:0:0:2:0:0:0:3
1:0:0:2::3

1:0:0:8:8:0:0:3
1::8:8:0:0:3

@DigitalTrauma виправлено. Я шукав "0: 0: 0 ...", і він фіксував останні 0
Nick T,

Ти справді не чуєш сьогодні достатньо слова «упирається»
Клавдіу,

Жук? Ця програма була прийнята, 1:2:3:4::a:b:c:dале відхилена ::2:3:4:a:b:c:dі 1:2:3:4:a:b:c::. Я вважаю, що це було неправильно всі три рази.
kernigh
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.