Чи повинні ми дружити?


30

Зауважте, це питання, в першу чергу, зосереджене на

Вступ

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

Технічні умови:

Ваша програма повинна бути REPL (цикл читання Eval-друку) підтримує 3 типи команд: FRIEND, SUGGESTі KNOW.

FRIEND X Y- Вказує, що це Xі Yє друзями в соціальній мережі.

  • Якщо X дружить з Y, то Y дружить з X

  • Може, але не повинен мати вихід

  • X завжди дружить з X

KNOW X Y - Виведіть правильне значення, якщо X і Y є друзями, помилково помилково

  • KNOW X X завжди буде виводити триєдне значення

SUGGEST X Y- Виведіть правдиве значення, якщо X і Y повинні бути друзями, помилково помилково. X і Y мають бути друзями, якщо:

  • X і Y не є друзями

  • X і Y мають принаймні одного друга

Ви маєте право на заміну FRIEND, SUGGESTі KNOWз вашими власними рядками, але ви повинні відзначити , що рядок , яку ви замінили кожну команду с.

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

Кількість людей у ​​соціальній мережі Nстановить від 1 до 100 000, але може бути будь-яка кількість «посилань на друзі» (краї).

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

Тестові справи

FRIEND A B
FRIEND A C
FRIEND B D
SUGGEST A B -> Falsy, as they are friends
SUGGEST A D -> Truthy, as they share B as a common friend
SUGGEST C D -> Falsy, they do not share a common friend
KNOW D B -> Truthy, they are friends
KNOW B C -> Falsy, not friends
=============
FRIEND Tom Tim
KNOW Tom Tim -> Truthy
KNOW Tim Tom -> Truthy
KNOW Tom Kit -> Falsy
=============
KNOW Tim Kit -> Falsy
FRIEND Tim Tom
KNOW Tim Kit -> Falsy
FRIEND Tom Kit
SUGGEST Tim Kit -> Truthy
=============
FRIEND X Y
SUGGEST X Y -> Falsy since X is friends with X

Ось ще кілька тестових випадків у формі зображення

Умова виграшу

Це , найкоротший виграш коду!


Наприклад, чи можемо ми почати з введення списку всіх людей у ​​мережі, наприклад {A, B, C, D}?
Грег Мартін

2
Наявність тестових випадків у текстовій формі було б набагато кориснішим.
Грег Мартін

1
Чи можемо ми отримати команду після команди FRIEND?
ов

7
SUGGEST UK EU.
WBT

1
@Thunda в Python, використовуючи вбудований REPL, потрібні два зайвих символи в команді. Чи повинні такі мови додавати додаткові байти до загальної довжини програми?
Кінтопія

Відповіді:


44

SWI-Prolog, 62 47 41 байт

X*Y:-X+Y;Y+X;X==Y.
X?Y:-not(X*Y),X*Z,Y*Z.

Пролог не надто часто корисний, але коли це просто красиво. Ми будемо використовувати, a+bщоб помітити, що aє друзями b, a*bщо aзнає, bі a?bщо bслід запропонувати aчи ні. Перший рядок просто говорить, що X*Yце правда, якщо вона є X+Y, Y+Xабо X == Yце правда. Це реалізує симетрію знання іншого. Запитувати, чи має бути пропозиція, неймовірно просто. Ми просто запитуємо, чи є Zтака, що X*Yпомилкова іX*Z і Y*Zє правдою. Точно так, як описано в виклику.

Якщо ви збережете це як файл (напр friends.pl ) та відкриєте SWI-Prolog з цим файлом ( prolog -l friends.pl), ви потрапляєте у REPL.

Ви можете стверджувати дружби так:

assert('a' + 'b').
assert('a' + 'c').
assert('b' + 'd').

Ви можете перевірити, чи знають люди одне інше чи пропозиція:

'a'*'b'.
'a'?'d'.

Ви повинні бути в змозі зберегти купу байтів, замінюючи k(X,Y)на X*Yі те саме, на fіs використанням різних операндів. 21 байт, якщо я правильно порахував.
Емінья

Не знаю, як вони працюють із твердженнями, тому я не впевнений f.
Емінья

12
Цілком іронізує структуру даних, що формує частину питання. Дивовижний.
Thunda

@Emigna я реалізував це, але це не врятувало стільки, скільки ви порахували.
orlp

Я тестував це як це в 41 байт. У мене немає відповіді, щоб спробувати це, хоча я не знаю, чи працює він там інакше.
Емінья

15

PHP, 138 133 129 байт

PHP б'є Mathematica - рідкісне виникнення.

for(;$s=fgets(STDIN);$s>G?print$$a[$b]?$s<L:$s>L&&@array_intersect_key($$a,$$b):$$a[$b]=$$b[$a]=1)[,$a,$b]=explode(" ",trim($s));

відбитки 1для правди, порожня рядок для помилки. Запуск з -nrабо перевірити його в Інтернеті .
для призначення списку потрібен PHP 7.1; Імена користувачів чутливі до регістру і повинні виключати a, b,s .

зламатися

for(;$s=fgets(STDIN);                       # loop through input
    $s>G                                        # 2. evaluate command
        ?print$$a[$b]
            # command KNOW: true if $$a[$b]
            ?$s<L
            # command SUGGEST: true if !$$a[$b] and array_intersect_key returns truthy
            :$s>L&&@array_intersect_key($$a,$$b)
        # command FRIEND: set keys in $$a and $$b
        :$$a[$b]=$$b[$a]=1
)
    [,$a,$b]=explode(" ",trim($s));             # 1. parse user names to $a and $b
  • $s його слід обрізати, оскільки він містить символ нового рядка.
  • array_intersect_keyйого слід вимкнути, або це призведе до попередження для порожнього $$aабо$$b .
  • +18 +15 байт для всіх імен користувачів: Замінити$$a на $f[$a]і $$bз $f[$b].

12

CMD (Пакет), 50 + 20 + 135 = 205 байт

  • ДРУЗІ.CMD

    @for %%f in (%1.%1 %1.%2 %2.%2 %2.%1)do @set %%f=1
    
  • ЗНАТИ.CMD

    @call echo(%%%1.%2%%
    

    Друкує 1 для друзів, порожній рядок для незнайомців.

  • SUGGEST.CMD

    @call set k=0%%%1.%2%%
    @set k=1&if %k%==0 for /f "tokens=2 delims=.=" %%f in ('set %1.')do @call set k=%%k%%%%%%f.%2%%
    @echo(%k:~1,1%
    

    Відбитки 1або порожній рядок. Я думаю, що шість поспіль %може бути новим найкращим персоналом.


Це шалено дивовижно. Приємне рішення.
AdmBorkBork

6

Python 3, 122 118 + 2 = 120 байт

l={}
def f(*r):l[r]=l[r[::-1]]=1
k=lambda a,b:a==b or(a,b)in l
s=lambda a,b:1-k(a,b)and any(k(a,z)&k(b,z)for z,_ in l)

Використання точно так само, як відповідь ovs.


1
Для мене це досить очевидно, але вимоги говорять, що вам потрібно вказати, як використовувати ваш REPL та з якими командами. Може бути корисним тим, хто не знає пітона. (До речі, саме такий метод я б застосував.)
квінтопія,

6

Python 3, 163 149 143 + 2 = 145 байт

-6 байт завдяки @FelipeNardiBatista

l=[]
def f(a,b):l.extend([(a,b),(b,a)])
k=lambda a,b:a==b or(a,b)in l
s=lambda a,b:k(a,b)-1and{c for c,d in l if d==a}&{c for c,d in l if d==b}

Збережіть його у файлі та запустіть як python3 -i file.py
Використовувати
- f("a", "b")замість FRIENDS a b
- k("a", "b")замість KNOW a b
- s("a", "b")замість -SUGGEST a b

Вихід Falsey: 0, set (), False
Truthy вихід: не порожній набір, True

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


164 байти, коли не використовується інтерпретатор python як REPL:

f=[]
while 1:c,a,b=input().split();i=(a,b)in f;f+=c=="f"and[(a,b),(b,a)]or[(i+(a==b),-i+1and{c for c,d in f if d==a}&{c for c,d in f if d==b})];print(f[-1][c=="s"])

Використовує
- fдля FRIEND
- sдля SUGGEST
чогось іншогоKNOW

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


Запропонувати функцію порушено для другої ланки
Thunda

@Thunda виправив це
1717

Виправте мене, якщо я щось пропускаю, але замість цього l.extend([(a,b),(b,a)]), чи не можете ви просто так зробити l+=[(a,b),(b,a)]? (Я цього ще не перевіряв)
HyperNeutrino

Пробачте, я зрозумів свою помилку, яка викликає UnboundLocalError. Гарна відповідь до речі!
HyperNeutrino

якщо ви вилучите bool()з sфункції і використаєте 0, {}і Falseяк Falsey і, Trueі не порожній setяк Truthy, ви можете зберегти 6 байт
Феліпе Нарді Батіста,

5

Математика, 164 байти

f={}
p:=Union@@f
i=Position[p,#][[1,1]]&
m:=Outer[Boole@MemberQ[f,{##}]&,p,p]
a=(#[[i@#2,i@#3]]/._@__->0)>0&
F=(f=#~Tuples~2~Join~f;)&
K=m~a~##&
S=a[m.m,##]&&!K@##&

Визначає три основні функції F, Sі Kз бажаним поведінкою. Наприклад, послідовність команд

F@{David, Bob}
F@{Bob, Alex}
F@{Alex, Kitty}
F@{Daniel, David}
F@{David, Kit}
S[David, Alex]
S[Bob, Kitty]
S[David, Kitty]
S[David, Bob]
K[David, Bob]
F@{Kit, Kitty}
S[David, Kitty]

- останній тестовий випадок із зображення, пов'язаного в ОП; то Fкоманди дають ніякого висновку (єдина точка з коми , здається невеликою плату за це), в той час як шість Sі Kкоманди виходу

True
True
False
False
True
True

за бажанням.

У будь-який момент f- це список упорядкованих пар форми, {A, B}де Aвідомо B, в той час pяк список людей, які фігурують у якомусь елементі f. Виклик F@{A, B}додає чотири впорядковані пари {A, B}, {B, A}, {A, A}і {B, B}до f.

Також у будь-який момент mє матрицею суміжності основного графіка (людина примикає до себе та до всіх своїх Fмандрів); рядки та стовпці індексуються pта iперетворюють особу у відповідний номер рядка / стовпця. Функція помічника aприймає матрицю та двох людей як вхідні дані і шукає запис матриці, "координатами" якої є дві людини, повертаючись, Trueякщо число є позитивним і Falseякщо воно дорівнює нулю. (Можна також зателефонувати, aколи хтось із вхідних людей ще не розпізнається - наприклад, зробить запит «ЗНАТИ» або «ЗАПАШИТИ» перед будь-якими деклараціями ДРУГОГО або запитати про якусь бідну людину, яка не має друзів; це призводить до помилок, але правило /._@__->0змушує результат бути Falseбудь-яким.)

K[A, B]Отже, виклик шукає, чи m[A, B]є позитивним, що реалізує Kтепер дієслово. Матричний добуток m.m- це матриця довжиною 2 шляху, що містить кількість способів переходу від однієї людини до іншої по шляху довжиною 2; це дозволяє S[A, B]реалізувати Sнайвиразніший дієслово, доки ми додатково перевіряємо вручну ( &&!K@##), що люди, які вводять, вже не знають один одного.

Кумедний факт: безкоштовно, ця реалізація дозволяє оголосити кліками друзів-команда F@{A, B, C, D}еквівалентна все F@{A, B}, F@{A, C}, F@{A, D}, F@{B, C}, F@{B, D}, і в F@{C, D}поєднанні.


2

Python 2, 118 bytes

F=[]
def s(f,c):c=set(c);r=c in F;return F.append(c)if f%2 else not r^(4 in[len(x|c)for x in F])if f else 2>len(c)or r

Try it online!

Since I couldnt find repl online tool for python 2, I've added the TIO Nexus(in REPL format).

Query for option and its possible output

0 for Known - None

1 for Friends - True or False

2 for Suggest - True or False

Example of usage and sample output in an repl python interpreter.

>>> F=[]
>>> def s(f,c):c=set(c);r=c in F;return F.append(c)if f%2 else not r^(4 in[len(x|c)for x in F])if f else 2>len(c)or r
...
>>> s(1,['A','B'])
>>> s(1,['A','C'])
>>> s(1,['B','D'])
>>> s(2,['A','B'])
False
>>> s(2,['A','D'])
True
>>> s(2,['C','D'])
False
>>> s(0,['D','B'])
True
>>> s(0,['D','C'])
False

0

GNU sed, 158 + 2(rn flags) = 160 bytes

Оскільки sed є мовою, що базується на регулярних виразках, не існує примітивних типів, не кажучи вже про абстрактні структури даних. Дані мережі зберігаються як текст у вільному форматі, у цьому випадку як надмірні посилання друзів, як-от A-B;B-A;тощо, який потім узгоджується з різними шаблонами регулярних виразів.

G
/^F/{s:. (.+) (.+)\n:\1-\1;\1-\2;\2-\1;\2-\2;:;h}
/^K |^S /{s:(.) (.+) (.+)\n.*\2-\3.*:\1:;/^K$/p}
/^S /s:(.) (.+) (.+)\n.*(.+)-(\2.*\4-\3|\3.*\4-\2).*:\1:p

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

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

Використання: у sed не існує значень truthy / falesy, тому вихідний конвент, який я використовую, запозичений з bash, внаслідок чого непуста рядок вважається truthy, а порожня рядок - фальшивою.

  • F X Yдля FRIEND X Y. Він не має виходу.
  • K X Yдля KNOW X Y. Виходить "K" як непростий, і нічого, як хибний.
  • S X Y for SUGGEST X Y. Outputs 'S' as truthy, and nothing as falsy.

Explanation:

G
# append stored network data, if any, to the current input line
/^F/{
# if command is 'F' (FRIEND), for ex. 'F X Y'
   s:. (.+) (.+)\n:\1-\1;\1-\2;\2-\1;\2-\2;:
   # generate friend links, for ex. 'X-X;X-Y;Y-X;Y-Y'
   h
   # store updated network data
}
/^K |^S /{
# if command is either 'K' (KNOW) or 'S' (SUGGEST), for ex. 'K X Y'
   s:(.) (.+) (.+)\n.*\2-\3.*:\1:
   # search friend link 'X-Y'. If found, delete pattern except the command letter.
   /^K$/p
   # if only letter K left, print it (command is 'K', 'X' and 'Y' are friends)
}
/^S /
# if command is 'S', for ex. 'S X Y', but 'X' and 'Y' aren't friends
   s:(.) (.+) (.+)\n.*(.+)-(\2.*\4-\3|\3.*\4-\2).*:\1:p
   # search if 'X' and 'Y' have a friend in common (for ex. 'C'), and if so print
   #letter S. The search is for ex. 'C-X.*C-Y' and 'C-Y.*C-X'.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.