Еквівалентність Цезаря


24

Два рядки є "цільовим еквівалентом", якщо відстань (підрахунок) між відповідними символами однакова. Так, я склав цей термін. Ось приклад:

"Abc" і "Cde" рівнозначні тому, що

distance from a-c == 2
distance from b-d == 2
distance from c-e == 2

Капіталізація не має ніякого значення.

"Привіт" і "світ" не є рівнозначними Цезарю, тому що

distance from h-w == 15
distance from e-o == 10
distance from l-r == 6
distance from l-l == 0
distance from o-d == 15

"Abcd" і "Yzab" є еквівалентом Цезаря, тому що

distance from a-y = 24
distance from b-z = 24
distance from c-a = 24 (it wraps around)
distance from d-b = 24

Ви повинні написати повну програму, яка бере два рядки від STDIN, і виводить триєдине значення, якщо вони є еквівалентом Цезаря, і хибне значення, якщо вони не є.

Дійсне введення

  • Оскільки велика література не має значення, це прийнятно, якщо ваша програма вимагає, щоб вхід був у всьому регістрі, у верхньому регістрі чи будь-якій суміші, яку ви хочете, доки це вказано у вашій відповіді.

  • На вході не буде пробілів чи розділових знаків.

  • Входи будуть однакової довжини.


8
Було б добре дозволити введення в якості аргументів командного рядка. Я збирався написати рішення C, але для читання з stdin потрібен досить тривалий код, особливо якщо у вас немає максимальної тривалості достроково.
Рето Коради

@RetoKoradi Чому ні? Це, мабуть, не виграє все-таки, оскільки C не точно відомий тим, що він був лаконічним.
DJMcMayhem

Правильно, я сумніваюся, що у C коли-небудь буде шанс на абсолютну перемогу. У кращому випадку я порівнюю рішення, які використовують "реальні";) мови програмування. Але навіть там інші мови, як правило, є більш компактними, особливо якщо вона включає обробку струн.
Рето Коради

4
Щоразу, коли я бачу це в списку питань, він має рівно стільки результатів, скільки відповідей.
Олексій А.

1
@AlexA. Я не звертав жодної уваги на коефіцієнт "вгору" та "відповідь", поки ви цього не вказали. Тепер це все, що я помічаю.
DJMcMayhem

Відповіді:


10

Pyth, 9 байт

}wm=.rzGG

Два рядки очікуються в малій, розділеній новою лінією.

Демонстрація.

Як це працює:

.rє функцією обертового перекладу Pyth. Він відображає кожен елемент у першому аргументі від його першого виникнення у другому аргументі до наступного запису у другому аргументі. У цьому випадку другий аргумент - Gце алфавіт з малі літери, тому це еквівалентно зсуву Цезаря на 1.

Якщо =поставити перед функцією, вона робить її на місці. Таким чином, =.rzGпризначається кесарів зміщення zна один до z. Зверніть увагу, що zініціалізовано до першого рядка введення в Pyth.

Цей вираз використовується всередині карти. m=.rzGGзастосовує це перетворення z26 разів, один раз для кожного елемента Gта зберігає результати у списку. Це дає перелік усіх можливих змін Цезаря z.

Нарешті, }wперевіряє, чи є наступний рядок введення у цьому списку.


14

CJam, 17 12 11 байт

Денніс зберег 1 байт.

ll.m26f%)-!

Перевірте це тут.

Очікує, що перший рядок буде нижній регістр, а другий - великим. Друкується 1для рядків, еквівалентних Цезарю та 0іншим способом.

Пояснення

ll           e# Read two lines of input.
  .m         e# Take the differences of corresponding characters.
    26f%     e# Take the differences modulo 26.
        )-   e# Remove all copies of the last difference from the array. This will 
             e# yield an empty array if and only if all differences are the same.
          !  e# Logical NOT, which yields 1 for an empty array and 0 otherwise.

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


1
Якщо вам потрібно, щоб перше слово було прописним, а друге - великим, ви можете 26f%зберегти один байт.
Денніс

Ви можете скористатися умовою оболонки ( stackoverflow.com/questions/2933843/… ), щоб наблизити її до відповіді Pyth.
VicAche

1
@VicAche Прийнята конвенція полягає в тому, щоб інтерпретувати правду та хибність будь-яким способом, яким її тлумачить ваша мова. Крім того, якщо я видалив, у !мене не було б 0 або 1, а порожній або не порожній масив.
Мартін Ендер

9

Python2, 68 67 70 69 Байт

print len({(ord(y)-ord(x))%26for x,y in zip(*raw_input().split())})<2

Python3, 67 66 байт

print(len({(ord(y)-ord(x))%26for x,y in zip(*input().split())})<2)

Унгольф трохи важко, тому просто пояснюючи фрагменти:

  • zip(*raw_input().split())приймає введення, розбиває його на список із двох слів, припускаючи, що слова розділені пробілом. Після цього кожне слово передається як параметр zipфункції за допомогою *оператора. zipФункція створює список буквених пар, для букв в одній і тій же позиції.
  • (ord(y)-ord(x))%26for x,y in ... Це просто перетворює список двох літер в генераторне вираження відстаней між цими літерами.
  • {...} зводить цей вираз до набору, по суті викидаючи дублікати
  • len(...)<2 перевіряє, чи є в наборі лише один елемент (або 0 для порожніх рядків), що по суті означає, що всі літери мали однакову відстань.
  • print Виводи, які мають значення

Завдяки xnor за те, що він нагадував, мене set(...)можна замінити, {...}а пробіл раніше forне потрібно. Також завдяки Josay для <=1для <2оптимізації.


Досить схоже на моє рішення, розміщене приблизно в ту саму хвилину. Ви були розумніші за мене, щоб піти на вхід, але ви можете зменшити значення <=1в «<2».
SylvainD

1
Ви можете зробити розуміння набору безпосередньо, {...}а не set((...)). Ваш код повинен насправді надрукувати результат.
xnor

@KillianDS Правила за замовчуванням вимагають друку в STDOUT або повернення (не оцінка REPL), і тут друк вказаний ОП. В іншому випадку загальним найкоротшим способом є використанняlambda для економії на написанні printабо return.
xnor

1
До речі, ви раніше не займаєте місця for; лексер Python правильно розбивається26for .
xnor

5

APL (15)

1=≢∪26|-⌿⎕A⍳↑⍞⍞

Букви повинні мати великі літери, а друкуються або, 1або 0так:

      1=≢∪26|-⌿⎕A⍳↑⍞⍞
ABCD
YZAB
1

      1=≢∪26|-⌿⎕A⍳↑⍞⍞
HELLO
WORLD
0

Пояснення:

  • ↑⍞⍞: прочитайте два рядки з клавіатури та розташуйте символи в матриці N × 2.
  • ⎕A⍳: для кожного символу знайдіть, у якому положенні він знаходиться ⎕A(великий алфавіт).
  • -⌿: для кожного стовпця віднімайте друге значення від першого значення
  • 26|: візьміть мод-26 кожного з цих номерів.
  • Якщо рядки еквівалентні Цезарю, усі числа у цьому списку тепер рівні, тому:
  • ≢∪: знайдіть у списку кількість унікальних значень
  • 1=: порівняйте це з 1.

Я ніколи не буду підтримувати APL :)
orlp

@AlexA. Я використовую Dyalog APL 14. Якщо у вас є Raspberry Pi, це безкоштовно; для студентів це також безкоштовно; інакше ви можете завантажити незареєстровану версію, яка є нагг, але в іншому випадку функціонально ідентична реальній. dyalog.com TryAPL, до речі, заснований на цьому.
Марина

Мені буде цікаво почути ваші думки щодо Dyalog vs. GNU APL, ngn / apl та APLX, хоча коментарі насправді не місце для такої дискусії. ;)
Олексій А.

3

J, 19 байт

1=[:#@~.26|-&(3&u:)

Листи в одній позиції повинні мати один і той же регістр.

Після перетворення обох вхідних рядків у їх представлення кодової точки з &(3&u:)порівняємо 1з довжиною #нуля ~.модуля 26 26|різниці- двох масивів. Нуб буде, 1якщо всі відстані Цезаря однакові.

Використання:

   'abcd' (1=[:#@~.26|-&(3&u:)) 'yzab'
1

Спробуйте його онлайн тут.


3

Юлія, 91 87 83 байт

a=readline()
b=readline()
show(length(Set([mod(a[i]-b[i],26)for i=1:length(a)]))<2)

Недоліки + пояснення:

# Read two strings from STDIN
a = readline()
b = readline()

# Get the absolute difference mod 26 of the character values in the strings
x = [mod(a[i] - b[i], 26) for i = 1:length(a)]

# Construct a set consisting of the elements of x. If the set has only a
# single element, the strings are Caesar equivalent. This will print a
# boolean value to STDOUT.
show(length(Set(x)) < 2)

Це використовує той факт, що рядки в Джулії можна розглядати як масиви символів, а арифметичні операції можна виконувати на символьних значеннях. Рядки введення можуть мати будь-яку суміш з великої літери, доки велика література в кожному положенні збігається між рядками.


3

C99, 92 байти з помилкою   101 92 байт

  r,i;main(z,a)char**a;{for(;z=a[2][++i];)r|=(a[1][i]-z+*a[2]-*a[1]+52)%26;putchar(49-!!r);}

Досить прямо; припускає, що слова надходять як перший і другий аргументи відповідно. Укладено з -std=c99.


Це дає неправильний результат для другого введення вибірки.
Рето Кораді

Ти маєш рацію, я пропустив це. Виправлено.
rr-

3

Javascript ( ES7 проект ), 87 байт

Потрібен той самий випадок.

(p=prompt)(![z=(a[c='charCodeAt'](i)-b[c](i)+26)%26 for(i in b=p(a=p()))].some(x=>x^z))


2

CJam, 13 байт

{r(fm26f%}2*=

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

Спробуйте тут . ( Firefox тут .)

Шкода, що варіанти APL не підтримують арифметику символів ...

Пояснення

{
    r       e# Read a word.
    (f-     e# Return each character value minus the first character.
    26f%    e# Mod 26.
}2*         e# Repeat 2 times.
=           e# Check if they are equal.

2

Перл, 80

Редагувати : невдала оптимізація прослизнула в код гольфу. Тепер він відповідає версії, що не має волі. (Хоча кількість байтів було правильним.)

@a=unpack"W*",<>;for(<>=~/./g){$n=ord()-shift@a;$p=!$c++||$p&&$n==$o;$o=$n}say$p

Запустіть програму Perl версії 5.10 ( perl -M5.10.0або perl -E …) для say(). Трохи розширена версія:

@a=unpack"W*",<>;             # read first string, split and convert to numbers

for(<>=~/./g){                # reads the second string and splits it
   $n=ord()-shift@a;          # convert next character of second string and compare
   $p= !$c++ || $p && $n==$o; # compare differences (special case for first char)
   $o=$n
}

say $p

Код виводиться 1(truthy в Perl), якщо рядки еквівалентні Цезарю, а порожня рядок (фальшива в Perl), якщо вони не є. Якщо це занадто вільне тлумачення, мені потрібно додати 2 байти для say$p+0, які друкує1 або 0.

Шрифт символів повинен відповідати вводум.


Виходячи з коментарів до вищезазначеного питання, ви також можете взяти введення як аргументи командного рядка. Ви можете використовувати -iдля того, щоб взяти другий рядок, який би зберігав його у змінній $^I. Крім того, використання -Eзамість -eзапуску в командному рядку отримає вас sayбезкоштовно, тому ви можете використовувати його без додавання байтів. Спробуйте запустити це: perl -iteststring -E'say$^I'можливо, ви зможете скоротити це за допомогою -iтрюку.
hmatt1

Дякую @chilemagic, -iфокус акуратний (а я цього не знав!). У цьому випадку я не думаю, що це допомагає, оскільки $^Iтриває довше <>.
xebtl

@chilemagic О, і, відповідно до цієї дискусії , я ні в -M5.10.0якому разі не рахував байти . (Але я згадував -Eперемикач у редагуванні)
xebtl

2

Матлаб, 49 48 байт

Це було дійсно швидко. На жаль отримати струну від stdin досить дорого.

x=@()input('','s');sum(diff(mod(x()-x(),26)))==0

Зауважте, що вона, як і більшість, якщо не всі відповіді, враховує регістри.

EDIT: поголений один байт, визначивши анонімну функцію!



2

C, 97 байт

#define D (*a[2]++-*a[1]+++26)%26
d,r;main(int c,char**a){for(d=D;*a[1];r|=d-D);puts(r?"N":"Y");}

1
Так! Ви відновили рівновагу!
DJMcMayhem

Ви можете зберегти 4 символи, якщо повторно використовувати dта оголоситиa тип зовнішніх параметрів, таких як: d,r;main(int c,char**a){r;main(d,a)char**a;{
rr-

1

Scala, 57 байт

(readLine zip readLine map(x=>x._1-x._2%26)toSet).size==1

Трохи довше, ніж інші, і по суті еквівалентний, але він відрізняється різним стилем мови!

У мене також є ця версія (56 байт):

(readLine zip readLine map(_._1-x$1._2%26)toSet).size==1

Але я не знаю, чи працює х $ 1 збіг чи за дизайном ...


1
Це справді дивно, як x$1працює, не xвизначаючись ніколи?
Дан Гец

@DanGetz Я впевнений, що це компілятор. Я можу задати питання про переповнення стека щодо нього: D
Інші

1

Python 2, 80 байт

Бере 2 строки з аналогічною обробкою з stdin, розділених пробілом:

s,t=raw_input().split();print len(set((ord(c)-ord(d))%26 for c,d in zip(s,t)))<2

Тестували на наступних тестових випадках:

tests = [
    ("abc", "abc", True),
    ("abcd", "abc", False),
    ("abc", "cde", True),
    ("Abc", "Cde", True),
    ("abc", "deg", False),
    ("Hello", "World", False),
    ("Abcd", "Yzab", True),
    ("", "", True)
]

for s, t, v in tests:
    if len(s) == len(t): # I didn't read that at first
        assert v == (len(set((ord(c) - ord(d)) % 26 for c, d in zip(s, t))) < 2)

1

Пітон 2 - 241 237 188 147 байт

Вводиться як введення рядків у лапки, розділене пробілом. Там повинен бути кращий спосіб ..

s=[[ord(x)for x in y]for y in input().split()];v=[];v=[v+[(s[1][i]-s[0][i])%26]for i in xrange(0,len(s[0]))];v=sum(v,[]);print sum(v)//v[0]==len(v)

Безголів (260 непарних байтів)

strs = [[ord(x) for x in y] for y in raw_input().split()]
vals = []
for i in xrange(0, len(strs[0])):
if strs[0][i]<strs[1][i]:
    vals += [strs[1][i]-strs[0][i]]
else:
    vals += [26-(strs[0][i]-strs[1][i])]
return sum(vals)//vals[0] == len(vals)

Я впевнений, що ви можете зробити всі змінні в 1 символ довгими і зберегти купу байтів. Ви також повинні додати 4 до свого рахунку, оскільки ви очікуєте 4 "с додаткових в своєму введенні.

@Reticality Я не можу повірити, що я не скоротив змінні .. аматорський хід. Я додав 2 до кількості байтів, оскільки не пояснив належним чином; вхід працює як "abc cde".
Кейд

1

R, 83 84

Настільки ж, як і інші рішення. Перетворити рядки у вектор цілих чисел. Змініть різницю векторів на 26. Зробіть унікальний список, оскільки перевірити довжину 1. Очікує, що випадок буде однаковим у відповідних символах у кожному рядку.

length(unique(((S=strtoi)((R=charToRaw)((I=readline)()),16L)-S(R(I()),16L))%%26))<2

Він чекає введення двох рядків

> length(unique(((S=strtoi)((R=charToRaw)((I=readline)()),16L)-S(R(I()),16L))%%26))<2
abcdefghijklmnopqrstuvwxyz
opqrstuvwxyzabcdefghijklmn
[1] TRUE
> length(unique(((S=strtoi)((R=charToRaw)((I=readline)()),16L)-S(R(I()),16L))%%26))<2
Hello
World
[1] FALSE
> length(unique(((S=strtoi)((R=charToRaw)((I=readline)()),16L)-S(R(I()),16L))%%26))<2
Bob
Nan
[1] TRUE
>

Ви можете зберегти байт за допомогою, <2а не ==1.
Олексій А.

Ви можете зберегти 3 байти, просто 10

@AlexA. Дякую Алекс, я пропустив цю ... і тепер я сумую за цим :)
MickyT

@Reticality: Як?
Олексій А.

@Reticality На жаль, він поверне один або більше одного.
MickyT

1

Матлаб / Октав, 53 52

x=@()input('','s');isscalar(unique(mod(x()-x(),26)))

Усі дані мають бути в одному випадку.

На жаль, Matlab не дуже хороший із введенням користувача. Як анонімний обробник, це може бути лише 35 байт:

@(a,b)isscalar(unique(mod(a-b,26)))

Матлаб трактує символи рядка як вектор чисел. Знімання робить нас їх різницею і uniqueперетворює цей вектор у вектор, що містить лише унікальні значення. Якщо є лише одне число, слова є еквівалентом caeser і isscalar повертає 1, інакше воно поверне 0.


Ой! Ще один запис Matlab! На відповіді дивився лише після відповіді на себе.
Oebele

щойно з’ясувавши, ви можете зберегти один байт, визначивши вхід x = @ () ('', 's');
Oebele

@Oebele Спасибі! Я думаю, що я почну спробувати більше проблем із гольфом в Matlab, я вважаю це насправді досить цікавим.
FryAmTheEggman

Так, це так. Для багатьох проблем це може бути дуже стислим з його матричним матеріалом. У Octave є трохи більше вільного синтаксису, який іноді може також зберегти ще кілька байтів, наприклад визначення вбудованої змінної.
Ебеле

1

баш, 71 48

Використання «стандартної» програми Unix caesar(6) .

Нова версія (з великою допомогою від @DigitalTrauma):

read a b;seq -f"caesar %g <<<$a" 26|bash|grep $b
  • Введення має бути на одній лінії, розділеної пробілами
  • Шрифт символів повинен відповідати вводум.
  • Відбитки 1для істинного або нічого для помилкового.

Якщо дозволено введення аргументів командного рядка, його можна скоротити до 39 байт :

 seq -f"caesar %g <<<$1" 26|bash|grep $2

Стара версія запису:

 read a b;for i in `seq 26`;do [ `echo $a|caesar $i` = $b ]&&echo 1;done

48 байтів, на мій підрахунок: read a b;seq -f"caesar %g <<<$a" 26|bash|grep $bРезультат знаходиться у $?вбудованій змінній, де 0 == ФАЛЬСЬКА і 1 == ІСТИНА, як за стандартною семантикою оболонки.
Цифрова травма

@DigitalTrauma Це кілька чудових ідей! Особливо мені подобається seq -f | bashшматочок. Під час $?читання виклику результат не відповідає дійсності, але так само, як і мій код, ваш не видає нічого неправдивого і чогось істинного (за винятком прикордонного випадку двох порожніх вхідних рядків). У будь-якому випадку, було б схоже на обман, щоб використати все це у моїй відповіді, можливо, ви повинні подати своє.
xebtl

Не хвилюйтесь - я пропоную поради для гольфу, якими ви користуєтесь. Якби я хотів їх використовувати, я б уже так зробив :). Що стосується речі truthy / falsey, я схильний інтерпретувати її як те, що є правдою та неправдою у вашій даній мові - спробуйте [ 0 == 0 ] ; echo $?і[ 0 == 1 ] ; echo $?
Digital Trauma

1

> <> (Риба) , 50 байт

i:3b*(?v88+0.;n1<
0)?vc1.>~ri-&l?!^i-&:&-2d*%
;n0<

Очікує, що листи, що знаходяться в одній позиції, мають той самий регістр.

Пояснення

  • i:3b*(?vчитає перше слово в стек із 88+0.забезпеченням циклічного стрибка
  • ~ri-&вилучає ~роздільний простір із стека, повертає стек r(перша буква буде зверху), читає першу букву другого слова i, обчислює зміщення від першої літери першого слова -і зберігає його в реєстрі &.
  • l?!^i-&:&-2d*%0)?vчитає кожну наступну букву другого слова, підкреслюючи її від відповідної літери першого слова, яка знаходиться у верхній частині стека, підкреслює зміщення, &:&-збережене в регістрі, і перевіряє, чи є результат 0 мод 26 2d*%. Якщо не друкує 0, то закінчується 0n;. c1.забезпечує циклічний стрибок.
  • Якщо досягнуто кінця другого слова, програма надрукує 1 та припиниться 1n;.

0

КДБ (Q), 35 байт

{0=sum(1_-':)mod[;26](-)."i"$(x;y)}

Пояснення

                         "i"$(x;y)      / convert to ascii decimal
                     (-).               / get differences
             mod[;26]                   / mod 26
      (1_-':)                           / difference between the differences
 0=sum                                  / sum should be 0 if equivalent
{                                 }     / lambda

Тест

q){0=sum(1_-':)mod[;26](-)."i"$(x;y)}["abcd";"yzab"]
1b

0

Java 281

import java.util.*;enum C{E;Scanner s=new Scanner(System.in);public static void main(String[]z){char[]u=E.n(),v=E.n();int i=0,d=(u[0]-v[0]+26)%26;boolean e=true;for(;++i<u.length;)e&=d==(u[i]-v[i]+26)%26;System.out.print(e);}char[]n(){return s.next().toUpperCase().toCharArray();}}

розширено:

import java.util.*;
enum Caesar{
    Equivalence;
    Scanner input=new Scanner(System.in);
    public static void main(String[]z){
        char[]firstString=Equivalence.nextInput(),secondString=Equivalence.nextInput();
        int index=0,difference=(firstString[0]-secondString[0]+26)%26;
        boolean isEqual=true;
        for(;++index<firstString.length;)
            isEqual&=difference==(firstString[index]-secondString[index]+26)%26;
        System.out.print(isEqual);
    }
    char[]nextInput(){
        return input.next().toUpperCase().toCharArray();
    }
}

Я міг би заощадити 14 байт, якби я позбувся перетворення всього на великі регістри, але мені здається, що це більш повно, щоб залишити це.


0

Желе , 5 байт

Oạ/ċ2

Спробуйте в Інтернеті!

Виводить додатне ціле число для еквівалента, 0 інакше

Як це працює

Oạ/ċ2 - Main link. Argument A (a list of strings)  e.g. ["abc", "cde"]

O     - Ordinal. Cast to code point                     [[97, 98, 99], [99, 100, 101]]
  /   - Reduce the list by...
 ạ    -   absolute difference                           [2, 2, 2]
   ċ2 - Count the number of 2s in the list              3
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.