Визначте, чи рівні рядки


29

Ваше завдання просте . Визначити , якщо один рядок дорівнює інший (не адреси, то значення) без використання операторів рівності (наприклад ==, ===чи .equal()) або нерівність ( !=, !==) нічого подібного на інших мовах. Це означає де завгодно! Ви не можете використовувати цих операторів ніде в коді. Однак ви можете використовувати перемикачі, такі як, наприклад !exp, ви безпосередньо не порівнюєте exp != with something else.

Крім того, ви не можете використовувати будь-які функції, такі як strcmp , strcasecmp тощо.

Що стосується операторів порівняння ( >=, <=, >, <), вони також заборонені . Я розумію, що деякі відповіді включають це, але мені дуже хотілося б побачити більше відповідей, які не межують з оператором рівності.


Показаний приклад використання PHP:

<?php

$a = 'string';
$b = 'string';

$tmp = array_unique(array($a, $b));

return -count($tmp) + 2;

Просто поверніть true або false (або щось, що оцінюється в мові, на true або false, як 0 або 1), щоб вказати, чи збігаються рядки. Рядки повинні бути жорстко кодованими, як це бачиться у наведеному вище прикладі. Рядки не повинні рахуватися в гольфі, тому якщо ви оголошуєте змінну перед рукою, не рахуйте декларацію.


1
Потрібно вивести результат або просто написати функцію, щоб повернути буль? Якщо потрібно написати повну програму, це могло б скласти або перервати відповіді мовами з (відносно) значущою табличкою для створення функціонуючих виконуваних файлів, таких як Java та C # (така природа звіра, але ця проблема мало що заважає конкретних вказівок, залишаючи багато для тлумачення / вибору). І як нам брати струни? Жорстке кодування, зчитування з STDIN, передається як аргументи командного рядка?
Тоні Елліс

Це [код-гольф] чи [популярність-конкурс]? Це не може бути обом.
Гарет

Вибачте, я змінив свої запитання, щоб відобразити обидва коментарі.
Девід Чен

Так дозволена нерівність?
user80551

Якщо рядки мають бути закодованими не раз (кожен), чи потрібно я рахувати їх довжину?
користувач80551

Відповіді:


34

Пітон 49 45 18 22 15 14

(+ 3, якщо враховуються рядкові змінні)

print{a:0,b:1}[a]

Рядок повинен бути жорстко закодований при двох входах aі одному виникненні в bоточенні лапок.

aі bмає бути попередньо ініціалізовано до рядків.


Оболонка Пітона, 9

(+ 3, якщо враховуються рядкові змінні)

{a:0,b:1}[a]

Вихід в оболонці

>>> a = 'string'
>>> b = 'string'
>>> {a:0,b:1}[a]
1
>>> a = 'string'
>>> b = 'stringgg'
>>> {a:0,b:1}[a]
0
>>> {'string':0,'string':1}['string']
1
>>> {'stringggg':0,'string':1}['stringggg']
0
>>> 

Пояснення

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

EDIT: OP дозволено 0/1 замість False / True, а також використання попередньо ініціалізованих змінних.


@manatwork Golfscript та perl нижче використовують 0/1, я не можу це використати?
користувач80551

@manatwork Готово
користувач80551

Я рахую 16 замість 13 для вашого другого рішення.
Абхіджіт

@Abhijit aі bне включатись, рядки повинні бути жорстко закодовані, тому я додав + 2 * len (str1) + len (str2) + 6 (')
user80551

+1 для розумних, але це вже далеко не найкоротше;)
лавина

20

Пітон ( 17 11):

b in a in b

(Перевіряє, чи міститься b в a, а в b, якщо це не було зрозуміло з коду.)

Альтернативний пітон: ( 8 7)

отриманий з рішення Go Tom:

b in[a]

Бонус: це працює для будь-якого типу.

Редагувати:

Зачекайте секунду, просто прочитайте, що ви також можете безпосередньо програмувати рядки, і вам не доведеться рахувати лапки ... (або, принаймні, те, що робить golfscript). Отже ... Пітон нарівні з гольфскриптом? О мій!

Альтернативна альтернатива Python ( 5 4):

(дякую Клавдіу)

"string"in["string"]

оригінал:

"string" in["string"]

Альтернативна альтернатива Альтернатива Бенді-рулі Пітон (2):

"string"is"string"

Нічого не було сказано про ключові слова порівняння (це не серйозне подання, просто щось, що мені трапилось ...)


2
Ви можете використовувати b in a in b. І не потрібно ...
Джордж

2
Тепер це дублікат відповіді Віллема .
манатура

Ви можете зменшити її до семи символів, видаливши пробіл між inі [a]. тобто b in[a]повинні працювати.
user3002473

О, не знав цього. Дякую :)
ɐɔıʇǝɥʇuʎs

Вражає! Також цього не знав
Віллем

14

JavaScript, 11 10

Рядки повинні зберігатися в a і b.

!(a>b|a<b)

Редагувати: спасибі Денні за вказівку, |досить замість||


5
Ні, я використовую більше і менше, ніж оператори. Вони не були заборонені у конкурсі.
Адам Сабо

2
+1. Це також працює однаково на багатьох інших мовах.
Архетипний Павло

3
Я можу помилятися, але ви не можете його видалити |?
Денні

3
Безумовно, нагляд за правилами - функції порівняння заборонені, як і оператори рівності та нерівності , але оператори порівняння не згадуються.
user2357112 підтримує Моніку

2
@philcolbourn Так, правила змінилися вчора, але відповідь - 2 дні.
Бакуріу


8

Python - 11 (без рядків)

>>> a = 'ss'
>>> b = 's'
>>> a in b in a
False

У тому ж дусі: a<=b<=aщо всього 7 символів. Хоча я не знаю, чи <=вважали б це порівняння "нерівністю". З питання випливає, що будь-яке порівняння, яке не перевіряє рівність, добре, що дозволило б <=.
Бакуріу

так, приємний @Bakuriu, і я згоден, його не зовсім зрозуміло, коли правила порушені чи ні. "in" зрештою такожomeome як містить рівне твердження.
Віллем

6

GolfScript (5 символів)

'string1''string1'].&,(

Досить простий порт реалізації еталонної програми PHP. Залишає 0(= false) на стеку, якщо рядки однакові, або 1(= true), якщо вони різні.


не працює для мене: 1якщо рядок однаковий і 2якщо вони різні. 'string1''string1'].&,1&твори
guy777

@ guy777, це передбачає, що стек на початку пустий. Питання щодо фрагментів програми досить розпливчасте. Ви, ймовірно, випробовуєте це як цілу програму і починаєте з порожнього рядка на стеку від stdin.
Пітер Тейлор

5

Javascript (45 байт):

Ось ще одне рішення у Javascript.

var a='string',b='string',c=!a.replace(b,'');

Простір важливий.

cповинно бути true.


Тільки !a.replace(b,'') зараховується. Тож кількість символів повинна бути 16. Насправді, деякі люди навіть рахують її 14, оскільки ви можете вказати рядок безпосередньо.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

5

C ++, 63 58 56

const char* a = "string";
const char* b = "string";
int main(){while(*a**b*!(*a^*b))++a,++b;return!(*a^*b);}

2
Ви могли б піти autoзамість цього const char*?
альдо

Я думаю, що так, але оскільки правила кажуть, що струнні змінні не зараховуються до числа символів, я не намагався їх гольфувати.
mattnewport

Не могли б ви скласти кроки під час тесту і залишити тіло порожнім? І якщо ви перейдете на c замість c ++, видаліть int на початку.
Оріон

Я не бачу жодного способу зменшити кількість символів шляхом складання кроків у тесті час, не потрапляючи на ту саму помилку доступу до рядка минулого кінця, на який я вказав у відповіді Абхіджіт С. Приріст a і b потрібно лише тоді, коли проходять обидва тести (ні a, ні b не вказують на нульовий термінатор, а a дорівнює b). Напевно, є спосіб покращити це, але я не зміг його знайти!
mattnewport

3

coreutils: uniq -d

Просто введіть свої два рядки в якості стандартного вводу труби і не uniq -d | grep -q .буде надруковано нічого, але матиме зворотне значення успіху чи помилки. Якщо ви хочете надрукувати булева, просто замініть наuniq -d | grep -c .

Скільки символів? Я дозволяю тобі рахувати; uniq -d|grep -q .без зайвих пробілів у ньому 17 символів, але оскільки всю роботу виконує uniq, я б сказав, що це рішення є символом 0 символів на ... uniqвласній мові!

Насправді uniq -dбуде надруковано один рядок, якщо два рядки однакові, і нічого, якщо різні.


3

Рядки повинні зберігатися в a і b. Не буде працювати, якщо так і є null.

C #, 53

string.IsNullOrEmpty(a.Replace(b,"")+b.Replace(a,""))

C #, 28

a.Contains(b)&&b.Contains(a)

3

PHP - 49 символів

!(strlen($a)^strlen($b)|strlen(trim($a^$b,"\0")))

Не могло б щось подібне працювати: !strlen(str_replace($a,'',$b));воно повинно повернути 1, якщо два рядки рівні?
Дамір Касіпович

@ D.Kasipovic Цікаво, але я думаю, що це не вдається $a == 'foo'і $b = 'foofoo':)
Jack

Щоправда, як щодо цього тоді він обмежує заміну до одного !strlen(preg_replace("/{$a}/", '', $b, 1));і становить 45 символів?
Дамір Касіпович

Я припускаю, що ви можете використовувати якір замість цього, але ще важливіше, що для цього знадобиться preg_quote () :)
Джек

3

APL ( 8 9)

Оновлення: стара не працює для рядків різної довжини.

{∧/∊⌿↑⍺⍵}
  • ↑⍺⍵: складіть матрицю з на першому рядку та на другому рядку, заповнивши пробіли пробілами.
  • ∊⌿: Для кожного стовпця подивіться, чи містить верхній рядок нижній рядок (як у старій версії).
  • ∧/: Візьміть логічне andдля всіх значень.

Старий:

{∧/⍺∊¨⍵}
  • ⍺∊¨⍵: для кожної комбінації елементів в і , перевірте, чи містить елемент з елемента з . Оскільки в рядку все це будуть поодинокі символи, а рядок містить себе, це в основному порівнюється кожною парою символів.
  • ∧/: прийміть логічне та всіх значень (якщо всі символи збігаються, рядки рівні)

3

Пітон - 12

not({a}-{b})

Це рішення використовує набори. Віднімання рівних множин призведе до порожнього набору, який має булеве значення False. Заперечення, що призведе до того, що значення True для a і b буде рівним рядків.

>>> a="string1"
>>> b="string2"
>>> not({a}-{b})
False

>>> a="string"
>>> b="string"
>>> not({a}-{b})
True

Редагувати: Дякую Пітеру Тейлору за те, що він вказав на непотрібний пробіл.


Який результат дає це a="s", b="ss"?
Пітер Тейлор

@PeterTaylor: З "s"!="ss"цього моменту вийде False. Чутливість корпусу також зберігається. Це навіть працює a="", b="s". Код не перетворює рядки в набори, але створює набори, що містять рядки.
Варик

Ах, {}це не те саме, що set(). Ви можете зберегти 1 char, видаливши пробіл.
Пітер Тейлор

@PeterTaylor: Дякую за вказівку на непотрібний пробіл. {a}еквівалентно set([a]).
Варик

Як щодо not {a}-{b}?
Вінстон Еверт

3

С - 62

e(char*p,char*q){for(;*p&*q&&!(*p^*q);q++,p++);return!(*p^*q);}

Випробуваний. Телефонувати якe(str1, str2)

Подумайте про це, якщо ви не рахуєте char*p,char*q, що здається справедливим, це всього 49 байт :)


Ласкаво просимо на сайт! Для проблем із кодовим гольфом ми радимо вам обрізати якомога більше байтів зі свого коду та розмістити кількість байтів у заголовку відповідей. Ознайомтеся з підказками для гольфу в C нитці, щоб отримати кілька хороших ідей
Джонатан Ван Матре

Вам не дуже потрібні npі nq. Зробиться один цикл, тому що якщо ви досягнете кінця однієї нитки перед іншою, вони матимуть інше значення.
Пітер Тейлор

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

*p&*qможе зупинити цикл занадто рано (наприклад '0'&'A'==0)
ugoren

@ugoren: Якщо *p=='0'& *q=='A', ми хочемо, щоб цикл припинився рано, оскільки ми знаємо, що рядки не рівні.
Еммет

2

Хаскелл - 9

elem a[b]

Зауважте, що це, як і багато записів тут, є лише виразом. Це не програма Haskell.


2

Ява - 162 147 символів

Ідея полягає в тому, щоб порівняти різницю кожного байта, однакові байти матимуть різницю 0. Програма буде кидати, java.lang.ArrayIndexOutOfBoundsExceptionколи байти відрізняються (спробуйте отримати доступ до негативного індексу) або коли рядки мають різну довжину. Він уловить виняток і поверне 0 (рядки не рівні), або поверне 1 в іншому випадку (рядки рівні).

Стислий:

String a = "12345";
String b = "12345";
byte[]x=a.getBytes(),y=b.getBytes();int z,i=a.length()-b.length();try{for(byte d:x){z=d-y[i];z=x[-z*z];i++;}}catch(Exception e){return 0;}return 1;

Звичайний:

String a = "12345";
String b = "12345";
byte[] byteArrA = a.getBytes();
byte[] byteArrB = b.getBytes();

int byteDifference = 0;
int i = a.length() - b.length();

try {
    for (byte aByte : byteArrA) {
        byteDifference = aByte - byteArrB[i];
        byteDifference = byteArrA[-byteDifference*byteDifference];
        i++;
    }
} catch (Exception e){
    return 0;
}

return 1;

Оператори порівняння існують у циклі.
ζ--

Дякую @hexafraction, я оновив відповідь, щоб не включати їх.
Мисливець

2

PHP

    $string = 'string';
    isset( ${'string'} );

Цей скрипт може не мати ніякої корисності, але принаймні це забезпечує спосіб порівняння рядків.

PHP

Інший:

    $string = 'something';
    $text   = 'something';
    return count( array( $string => 1 , $text => 1 ) ) % 2;

1
Вау дуже мила. І робити це так, це дає можливість використовувати будь-який рядок (з пробілами та unicode).
Девід Чен

2

Пролог 7

e(A,A).

Це використовує функцію відповідності шаблонів у Prolog для уніфікації двох аргументів до предиката, який ефективно перевіряє рівність еквівалентності, коли немає незв'язаної змінної .

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

?- e("abcd", "Abcd").
false.

?- e("abcd", "abcd").
true.

Технічно кажучи, поведінка цього рішення є поведінкою оператора об'єднання =/2, а не того ==/2, який перевіряє на еквівалентність терміна. Різниця показує, коли беруть участь незв'язані змінні. У цьому рішенні, коли надається незв'язана змінна, предикат повернеться, trueколи об’єднання буде успішним. Для порівняння, ==/2порівняємо порядок терміну без уніфікації.


2

PHP, 21

Цей виконує роботу за допомогою змінної непрямості.

$$a=$b;!!$$b;

Або, якщо вам не потрібно, щоб це було bool

$$a=$b;$$b;

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

$$a=$b;!($a.$b)||$$b;

що становить 21 ч.


Я очікував, що це дасть помилки, коли задаються рядки, які не є дійсними ідентифікаторами, але, на мій подив, це не так.
Пітер Тейлор

Дві проблеми: 1. Повертає істину при порівнянні "0" і "". 2. Повертає істину, коли $ b - це назва існуючої змінної (у поточній таблиці символів) зі значенням, яке перетворюється на істинне (наприклад, "GLOBALS" або "_SERVER" у глобальному масштабі, або "b" в будь-якій області), навіть коли $ b не дорівнює $ a.
Будь ласка, продовжуйте

2

CPython: 6

a is b

>>> a = 'string'
>>> b = 'string'
>>> c = 'STRING'
>>> a is b
True
>>> a is c
False

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

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


2

Мова математики / Вольфрам, 15 байт

2 - Length[{a} ∪ {b}]

Досить пояснює, встановлює кожну рядок як множину, а потім перевіряє довжину з'єднання двох наборів. Якщо рядки однакові, повертається 1, інакше повертається 0. Якщо мені дозволено повернути "2" для "різних" і "1" для "однакових", відніміть два байти.


2

C 342 гольф

#include <stdio.h>
#define N 100
#define P(x) printf("%s\n",x)
#define G(x) gets(x)
void e(int x){x?P("y"):P("n");}
int main(){
char s[N],t[N];char *p,*q;int r=0; int n=0,m=0;int i=1;p=s,q=t;
if((p=G(s))&&(q=G(t))){while (*p){n+=i*(int)*p;m+=i*(int)*q;i++;p++;q++;if(!(*q)){break;}}
if(!*p&!*q){if(!(m-n)){r=1;}}e(r);}
return 0;
}

Примітка: Visual Studio скаржиться, якщо ви не використовуєте їх безпечні методи, наприклад get_s. CodeBlocks з mingw компілюється без попереджень.

C 655 не в гольф

Код створює зважену суму символів для кожного рядка. Якщо різниця дорівнює нулю, вони рівні, включаючи 2 порожні рядки:

    #include <stdio.h>
#define N 100
#define P(x) printf(x)
#define G(x) gets_s(x)

void e(int x){ x ? P("equal\n") : P("not equal\n"); }
int main()
{
    char s[N], t[N];//words
    char *p = 0, *q = 0;
    int r = 0; //result 0=false
    int n=0, m=0; //weighted sums
    int i = 1; //char pos start at 1
    if ((p=gets_s(s)) &&
        (q=gets_s(t)))
    {
        while (*p)
        {
            n += i*(int)*p;
            m += i*(int)*q;
            i++;
            p++;
            q++;
            if (!(*q)){
                break;
            }
        }

        if (!*p && !*q){ //both same length strings
            if (!(m - n)){ r = 1; } //weighted sums are equal           
        }//else r=0, false=>not equal

        e(r);
    }
    else{
        P("error\n");
    }
    getchar();
}

Хороша робота, але вам, мабуть, варто пограти в неї.
Hosch250

Я не можу скласти ваше подання. Я отримую "Не визначені символи для архітектури x86_64:" _gets_s ", на які посилається: _main in golf-310cf2.o ld: символ (и) не знайдено для архітектури x86_64"
Стівен Мелвін

2

Пітон

Це довго і це не красиво, але це мій перший запис!

def is_equal(a,b):
    i=0
    a,b=list(a),list(b)
    if len(a)>len(b):
        c=a
        lst=b
    else:
        c=b
        lst=a
    try:
        while i<len(c):
            for j in c:
                if j not in lst[i]:
                    return False
                i+=1
    except IndexError:
        return False
    return True

2

PHP, 68 байт

Я припускаю, що вам заборонено використовувати будь-які оператори порівняння. Так <або >включаються.

Ідея полягає у використанні бітового XOR. У різних мовах цей оператор має різний синтаксис - я покажу приклад для PHP. Там це доступно в^ . На жаль, його поведінка з рядками не так добре, як могло б бути, тому вам потрібно буде перевірити довжину рядка раніше. Це тому, що в PHP xor зніме довгу струну до довжини коротшої струни.

Наступне - правильно працювати з рядками, оскільки сингл xorне дасть результату, доступного для подальших операцій у PHP. Ось чому unpack()і використовувався. Отже, код буде таким:

return !(strlen($a)^strlen($b)) & !array_filter(unpack('c*', $a^$b))

Це довше, ніж варіант з </, >але він не використовуватиме їх. Також важливим є те, що стосується жонглювання типу PHP (тому порожній масив буде переданий false). Або, можливо, є більш простий спосіб перевірити, чи містить масив ненульові члени ( Редагувати : поки я це вводив, є хороший результатtrim() в іншому відповіді , щоб ми могли позбутися операцій з масивом)

Але я вважаю, що є мови, на яких ми можемо робити просто a ^ b- буквально, отримуючи результат. Якщо це 0(оброблено з усіх отриманих байтів) - то наші рядки рівні . Це дуже просто і навіть простіше, ніж <або >речі.


1

grep 14 символів

Звичайно, я рахую лише grep-код; два рядки знаходяться на двох послідовних лініях у вході (або труба, або файл, або навіть інтерактивний сеанс).

$ echo -e 'string\nstring' | grep -cPzo "(?s)^(\N*).\1$"
1
$ echo -e 'string\nstring1' | grep -cPzo "(?s)^(\N*).\1$"
0
$ echo -e 'string1\nstring' | grep -cPzo "(?s)^(\N*).\1$"
0


1

Дуже шалений спосіб

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

$ echo -e 'string\nstring1' | sed -e '1s/^/#define /' | cpp | sh 2>/dev/null && echo true
$ echo -e 'string\nstring' | sed -e '1s/^/#define /' | cpp | sh 2>/dev/null && echo true
true
$ echo -e 'string1\nstring' | sed -e '1s/^/#define /' | cpp | sh 2>/dev/null && echo true

Хороший зустрічний приклад - порівняння "рядка" як першого рядка і "rm -Rf /" як другого рядка; просто перевірте як корінь і подивіться: він скаже "вірно", хоча обидва рядки очевидно не однакові.


1

JavaScript [18 байт]

(_={})[a]=1,!!_[b]

АБО

!!((_={})[a]=_)[b]

Це повернеться, trueякщо a == bі falseякщо a =/= b. Логіка позаду полягає у створенні об'єкта зі значенням aяк властивість та поверненні, 1або undefinedу випадку, якщо в цьому об'єкті bіснує або не існує властивості значення.


У правилах сказано, що ви можете повернути об'єкт, який оцінює як істинний, або хибний, тому !!не потрібно
James_pic

@James_pic Так, але в іншому випадку він повернеться 1або undefined(або об'єкт / undefinedдля другого випадку).
VisioN

Я інтерпретував правила так, що кажучи, що значення істинності y і false-y будуть робити замість істинних і хибних, тому я вважаю, що 1 або невизначений є досить хорошим.
James_pic

@James_pic Я просто хотів бути в безпечній стороні :) Якщо так, то 18-2 = 16 bytes.
VisioN

1

JavaScript [15 байт]

![a].indexOf(b)

Це повернеться, trueякщо a == bі falseякщо a =/= b. Сценарій шукає значення bмасиву, який містить єдиний елемент значення a.


1

С - 86 83

main(int i,char**v){return*v[1]&!(*v[1]++^*v[2]++)?main(3,v):!(*--v[1]^*--v[2]);}

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


Вам не потрібні місця навколо багатьох операторів. Наприклад, char** vможна записати як char**v. Є деякі винятки (на кшталт 42 / *pointer), але в більшості випадків пробіли можна безпечно видалити поблизу спеціальних символів.
Конрад Боровський

І аперсанд занадто багато. Сьогодні не зверху.
СБІ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.