私たちは友達になるべきですか?


30

これは主にに焦点を当てた質問であることに注意してください

前書き

Bacefookは、人々が友好的であることを望んでいます!そのため、彼らは友達を提案する新しいシステムを実装しています!あなたの仕事は、Bacefookが新しい提案システムを実装するのを支援することです。

仕様:

あなたのプログラムは、コマンドの3種類をサポートしているREPL(read-eval-printループ)でなければなりませんFRIENDSUGGESTKNOW

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には共通の友人が少なくとも1人います

FRIENDSUGGESTおよびKNOWを独自の文字列に置き換えることができますが、各コマンドを置き換えた文字列に言及する必要があります。

プログラムは、それがどのように機能するかを合理的に簡単に認識できる限り、望ましい方法で入力/出力を取り込むことができます。

ソーシャルネットワーク内の人の数は1〜100,000ですNが、「友人リンク」(エッジ)はいくつあってもかまいません。

まだ気づいていない場合、これはグラフ検索の問題です。これを実装するための(おそらく)最も簡単な(おそらく最速の)データ構造は、隣接行列です。

テストケース

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コマンドの後に出力できますか?
-ovs

7
SUGGEST UK EU
WBT

1
Pythonの@Thundaでは、組み込みのREPLを使用するには、コマンドに2つの余分な文字が必要です。このような言語は、プログラムの全長にこれらの余分なバイトを追加する必要がありますか?
キントピア

回答:


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を示す友人と記すために使用します。最初の行は、またはのいずれかが真である場合にそれが真であると単に示しています。これにより、お互いを知る対称性が実現されます。提案があるべきかどうかを尋ねることは非常に簡単です。偽であり、真であるようなものがあるかどうかを尋ねるだけです。チャレンジで説明したとおりです。ba*baba?bbaX*YX+YY+XX == YZX*YX*ZY*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
質問の一部を設計するデータ構造を完全におならします。すごい。
サンダ

@Emigna私はそれを実装しましたが、それはあなたが数えたほど節約しませんでした。
-orlp

41バイトでこのようにテストしました。私はそれを試すためのREPLを持っていないので、そこで動作が異なるかどうかはわかりません。
エミグナ

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

プリント1truthyため、falsy空の文字列。オンラインで実行する-nr、オンラインでテストします
リストの割り当てにPHP 7.1が必要です。ユーザー名は大文字と小文字が区別され、除外する必要がありますabs

壊す

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バイト

  • FRIEND.CMD

    @for %%f in (%1.%1 %1.%2 %2.%2 %2.%1)do @set %%f=1
    
  • KNOW.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または空白行。6連続%のsは、新しい個人的なベストかもしれません。


すごいすごい。いい解決策。
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の使用方法とコマンドを指定する必要があるとされています。Pythonを知らない人に役立つかもしれません。(ちなみに、これはまさに私が使用していた方法です。)
quintopia

6

Python 3、163 149 143 + 2 = 145バイト

@FelipeNardiBatistaのおかげで-6バイト

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

オンラインで試す


pythonインタープリターをREPLとして使用しない場合の164バイト:

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が修正
ovs

何かが足りない場合は私を修正してください、しかし、代わりにl.extend([(a,b),(b,a)])、あなたはちょうどできませんl+=[(a,b),(b,a)]か?(私はまだこれをテストしていません)
-HyperNeutrino

ああ、申し訳ありませんが、私は自分の間違いに気付きましたUnboundLocalError。ところでいい答えです!
ハイパーニュートリノ

あなたが削除した場合bool()s機能、および使用0{}およびFalseFalseyようとTrueし、空でないsetTruthyとして、あなたは6つのバイトを救うことができます
フェリペ・ナルディバチスタ

5

Mathematica、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@##&

三つの主要な機能を定義しFSし、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]

OPにリンクされた画像の最後のテストケースです。F6ながらコマンドは、(単一のセミコロンは、このためにお金を払うの小さな価格だ)何も出力が得られないSKコマンドが降伏します

True
True
False
False
True
True

望んだ通りに。

いつでもf、フォームの順序付きペアのリストです{A, B}A知っているB一方で、pいくつかの要素に登場する人々のリストですf。通話はF@{A, B}4順序対を追加して{A, B}{B, A}{A, A}、と{B, B}f

また、いつでも、 mで、基礎となるグラフの隣接行列です(人は自分自身とすべてのF仲間に隣接しています)。行と列はによってインデックスが付けられpi人を対応する行/列番号に変換します。ヘルパー関数aは、マトリックスと2人を入力として受け取り、「座標」が2人のマトリックスのエントリを検索しTrue、数値が正のFalse場合とゼロの場合に戻ります。(a入力者の1人がまだ認識されていないときに呼び出すこともできます。たとえば、FRIEND宣言の前にKNOWまたはSUGGESTクエリを作成したり、友達のいない貧しい人について尋ねたりすると、エラーがスローされますが、とにかく/._@__->0出力を強制しますFalse。)

K[A, B]したがって、呼び出しm[A, B]は正であるかどうかを調べ、Know動詞を実装します。マトリックス積m.mは、長さ2のパスマトリックスであり、長さ2のパスに沿ってある人から別の人に行く方法の数が含まれています。これによりS[A, B]Sさらに手動でチェックする限り、uggest verb を実装できます(&&!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バイト

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

オンラインでお試しください!

Python 2のreplオンラインツールが見つからなかったため、TIO Nexus(REPL形式)を追加しました。

オプションとその可能な出力のクエリ

既知の場合は0-なし

友人の場合は1-正誤問題

提案の2-真または偽

repl pythonインタープリターの使用例と出力例。

>>> 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フラグ)= 160バイト

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には真実/偽の値はないため、使用する出力規則はbashから借用されます。これにより、空でない文字列は真実と見なされ、空の文字列は偽と見なされます。

  • F X YのためにFRIEND X Y。出力はありません。
  • K X YのためにKNOW X Y。'K'を真実として出力し、偽物としては出力しません。
  • S X YのためにSUGGEST X Y。'S'を真実として出力し、偽物としては出力しません。

説明:

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'.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.