Цезарь эквивалентность


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

Да, я сомневаюсь, что у С когда-нибудь будет шанс на абсолютную победу. В лучшем случае я сравниваю с решениями, использующими «настоящие»;) языки программирования. Но даже там другие языки, как правило, более компактны, особенно если это связано с обработкой строк.
Рето Коради

4
Каждый раз, когда я вижу это в списке вопросов, у него столько же голосов, сколько и ответов.
Алекс А.

1
@AlexA. Я не обращал никакого внимания на соотношение голосов к ответам, пока вы не указали на это. Теперь это все, что я замечаю.
DJMcMayhem

Ответы:


10

Pyth, 9 байт

}wm=.rzGG

Две строки ожидаются в нижнем регистре и разделены новой строкой.

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

Как это работает:

.rвращательная функция перевода Пита. Он сопоставляет каждый элемент в первом аргументе от его первого вхождения во втором аргументе до следующей записи во втором аргументе. В этом случае вторым аргументом является 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 ... Это просто преобразует список из 2 букв в генераторное выражение расстояний между этими буквами.
  • {...} сводит это выражение к набору, по существу выбрасывая дубликаты
  • len(...)<2 проверяет, остается ли в наборе только один элемент (или 0 для пустых строк), что означает, что все буквы имеют одинаковое расстояние.
  • print выводит это значение

Спасибо xnor за напоминание о том, что меня set(...)можно заменить, {...}и до этого места forне требуется. Также благодаря Josay для <=1для <2оптимизации.


Довольно похоже на мое решение, опубликованное примерно в ту же минуту. Вы были умнее меня, чтобы пойти на вход, но вы можете уменьшить <=1до «<2».
SylvainD

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

@KillianDS Правила по умолчанию требуют печати в STDOUT или возврата (не для оценки REPL), и здесь OP указывает печать. В противном случае общий кратчайший путь заключается в том, 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 против 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)

Ungolfed + объяснение:

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

Это использует тот факт, что строки в Julia могут обрабатываться как символьные массивы и что арифметические операции могут выполняться над символьными значениями. Входные строки могут иметь любую комбинацию заглавных букв, которую вы хотите, при условии, что заглавные буквы в каждой позиции совпадают между строками.


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 Draft ), 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

Perl, 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(правда в 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

Matlab, 49 48 байтов

Это было действительно быстро. К сожалению, получить строку из stdin довольно дорого.

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

Обратите внимание, что он, как и большинство, если не все ответы, чувствителен к регистру.

РЕДАКТИРОВАТЬ: сбрил один байт, определив анонимную функцию!



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

Скала, 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

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

Ungolfed (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 с на вашем входе.

@ Ретикальность Я не могу поверить, что я не сокращал переменные .. любительский ход. Я добавил 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 байта, просто выводя 1или0

@AlexA. Спасибо Алекс, я пропустил это ... и теперь я скучаю по этому :)
MickyT

@Reticality: как?
Алекс А.

@Reticality К сожалению, он вернул бы 1 или больше, чем один.
MickyT

1

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

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

Все входные данные должны быть в одном и том же случае.

К сожалению, Matlab не очень хорош с пользовательским вводом. В качестве анонимного дескриптора это может быть только 35 байт:

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

Matlab обрабатывает символы строки как вектор чисел. Делая вычитание, мы получаем их различие и uniqueпреобразуем этот вектор в вектор, содержащий только уникальные значения. Если есть только одно число, слова эквивалентны caeser и isscalar возвращает 1, в противном случае возвращается 0.


Ой! Еще одна запись Matlab! Посмотрел ответы только после того, как отвечал сам.
Oebele

только что выяснили, что вы можете сохранить один байт, определив x = @ () input ('', 's');
Oebele

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

Да, это так. Для многих задач он может быть очень лаконичным с матричным материалом. Octave имеет немного более свободный синтаксис, который иногда может также сохранить еще несколько байтов, например, определение встроенных переменных.
Oebele

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 == FALSE и 1 == TRUE, согласно стандартной семантике оболочки.
Цифровая травма

@DigitalTrauma Это отличные идеи! Мне особенно нравится seq -f | bashнемного. Результат $?не действителен для моего чтения задачи, но, как и мой код, ваш ничего не выводит для false и что-то для true (за исключением пограничного случая двух пустых строк ввода). Во всяком случае, было бы похоже на обман, чтобы использовать все это в моем ответе, может быть, вы должны представить свой собственный.
xebtl

Не волнуйтесь - я предлагаю вам советы по игре в гольф. Если бы я хотел их использовать, я бы уже сделал это :). Что касается истины / фальши, я склонен истолковывать ее как то, что правда и ложь в вашем языке - попробуйте [ 0 == 0 ] ; echo $?и[ 0 == 1 ] ; echo $?
Цифровая травма

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 mod 26 2d*%. Если нет, выводит 0 и завершается 0n;. c1.обеспечивает зацикливание прыжка.
  • Если достигнут конец второго слова, программа печатает 1 и завершает работу 1n;.

0

KDB (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.