우리는 친구가되어야합니까?


30

이것은 주로 에 중점을 둔 질문입니다.

소개

Bacefook은 사람들이 더 친해지기를 원합니다! 그래서 그들은 친구를 제안하는 새로운 시스템을 구현하고 있습니다! 당신의 임무는 Bacefook이 새로운 제안 시스템을 구현하도록 돕는 것입니다.

명세서:

프로그램은 FRIEND, SUGGEST및 의 세 가지 유형의 명령을 지원하는 REPL (read-eval-print loop)이어야합니다 KNOW.

FRIEND X Y-되도록 지정 XY소셜 네트워크에서 친구입니다.

  • 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 명 이상입니다.

당신은 대체 할 수 있습니다 FRIEND, SUGGEST그리고 KNOW자신의 문자열,하지만 당신은 당신이 각 명령을 대체 한 내용을 문자열 언급해야합니다.

프로그램 작동 방식을 합리적으로 쉽게 인식 할 수 있다면 프로그램은 원하는 방식으로 입력 / 생성 출력을 취할 수 있습니다.

소셜 네트워크에있는 사람의 수는 N1에서 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} 있습니까?
Greg Martin

2
테스트 케이스를 텍스트 형식으로 작성하면 더 도움이됩니다.
Greg Martin

1
FRIEND 명령 후에 출력 할 수 있습니까?
ovs

7
SUGGEST UK EU.
WBT

1
내장 REPL을 사용하려면 Python의 @Thunda에서 명령에 두 개의 추가 문자가 필요합니다. 이와 같은 언어가 프로그램의 전체 길이에 여분의 바이트를 추가해야합니까?
quintopia

답변:


44

SWI- 프롤로그, 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*ba알고 b그리고 a?bb에게 제안한다 a여부. 첫 번째 줄은 단순히X*Y 또는 중 하나 X+Y인 경우에 . 이것은 서로를 아는 대칭을 구현합니다. 제안이 필요한지 묻는 것은 매우 간단합니다. 우리는 단지이 있는지 물어 그 같은 거짓과 와 마찬가지입니다. 도전에 설명 된대로 정확하게.Y+XX == YZX*YX*ZY*Z

이 파일을 파일 (예 friends.pl:) 로 저장하고이 파일 ( )과 함께 SWI-Prolog를 열면 prolog -l friends.plREPL에 빠지게됩니다.

다음과 같은 우정을 주장 할 수 있습니다.

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

사람들이 서로를 알고 있거나 제안해야하는지 확인할 수 있습니다.

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

당신은 대체 바이트의 무리 저장 할 수 있어야한다 k(X,Y)과를 X*Y과와 같은 fs다른 피연산자를 사용. 올바르게 계산하면 21 바이트.
Emigna

그래도 어설 션을 어떻게 사용하는지 잘 모르겠으므로 확실하지 않습니다 f.
Emigna

12
질문의 일부를 디자인하는 데이터 구조를 완전히 이해합니다. 놀랄 만한.
Thunda

@Emigna 나는 그것을 구현했지만 당신이 세는만큼 절약하지 못했습니다.
orlp

나는처럼 시험 41 바이트에서. 나는 그것을 시도 할 REPL이 없으므로 거기에서 다르게 작동하는지 모르겠습니다.
Emigna

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이 필요합니다. 사용자 이름은 대소 문자를 구분하고 배제한다 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
    
  • 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 연속 연속 %새로운 개인 최고 라고 생각 합니다.


대단해. 좋은 해결책.
AdmBorkBork

6

파이썬 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

파이썬 (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

온라인으로 사용해보십시오


파이썬 인터프리터를 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"])

용도
- fFRIEND
- sSUGGEST
-에 대한 아무것도KNOW

온라인으로 사용해보십시오


두 번째 링크에 대한 제안 기능이 중단되었습니다
Thunda

@Thunda가 고쳤습니다
ovs

내가 누락 된 것이 있으면 바로 잡으십시오. 대신 대신 l.extend([(a,b),(b,a)])할 수 l+=[(a,b),(b,a)]있습니까? (나는 이것을 아직 테스트하지 않았다)
HyperNeutrino

죄송합니다, 실수를 깨달았습니다 UnboundLocalError. 그건 그렇고 좋은 답변입니다!
HyperNeutrino

당신이 제거하면 bool()으로부터 s기능, 사용 0, {}False및 Falsey로 True하고이 비어 있지 setTruthy, 당신은 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]

OP에 링크 된 이미지의 마지막 테스트 사례입니다. F명령은 어떤 출력 (단일 세미콜론이 지불 할 작은 가격을 보인다) 산출 여섯 개 동안 SK명령 수율

True
True
False
False
True
True

바라는대로.

어느 순간, f형태의 순서쌍의 목록입니다 알고 있지만, 몇 가지 요소에 나오는 사람들의 목록입니다 . 호출은 네 개의 순서쌍 추가 , , ,과 에 .{A, B}ABpfF@{A, B}{A, B}{B, A}{A, A}{B, B}f

또한, 언제든지 m기본 그래프의 인접 행렬이 있습니다 (사람은 자신과 모든 F라이더에 인접 해 있습니다 ). 행 및 열에 의해 색인 pi대응하는 행 / 열 번호에 사용자를 변환한다. 도우미 함수 a는 행렬과 두 사람을 입력으로 취하고 "좌표"가 두 사람인 행렬의 항목을 조회 True하여 숫자가 양수 False인지 0인지를 반환 합니다. ( a예를 들어 친구 선언 전에 KNOW 또는 SUGGEST 쿼리를하거나 친구가없는 가난한 사람에 대해 질문하는 경우) 입력 된 사람 중 하나가 아직 인식되지 않은 경우 호출 할 수도 있습니다 . 어쨌든 /._@__->0출력을 강제합니다 False.)

Calling K[A, B] therefore looks up whether m[A, B] is positive, which implements the Know verb. The matrix product m.m is the length-2-path matrix, containing the number of ways to go from one person to another along a path of length 2; this allows S[A, B] to implement the Suggest verb, as long as we additionally check by hand (&&!K@##) that the input people don't already know each other.

Fun fact: for free, this implementation allows us to declare cliques of friends—the command F@{A, B, C, D} is equivalent to all of F@{A, B}, F@{A, C}, F@{A, D}, F@{B, C}, F@{B, D}, and F@{C, D} combined.


2

파이썬 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

온라인으로 사용해보십시오!

파이썬 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 바이트

Since sed is a regex based language, there are no primitive types, not to mention abstract data structures. The network data is stored as free format text, in this case as redundant friend links like A-B;B-A;etc., which is then matched against various regex patterns.

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

Try it online!

By design, sed runs the whole script for each input line. I recommend testing in interactive mode, to see the output of a command immediately after typing.

Usage: there are no truthy / falsy values in sed, so the output convention I use is borrowed from bash, whereby a non-empty string is considered as truthy, and an empty string as falsy.

  • F X Y for FRIEND X Y. It has no output.
  • K X Y for KNOW X Y. Outputs 'K' as truthy, and nothing as falsy.
  • 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'.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.