그래프 구성


15

이 도전에서, 당신의 임무는 일련의 지시문으로부터 무 방향 그래프를 구성하는 것입니다. 음이 아닌 각 정수마다 하나의 지시문이 있으며 각 그래프는 지정된 그래프를 새 것으로 변환합니다.

  • 지시문 0: 연결이 끊어진 새 노드를 추가하십시오.
  • 지시문 1: 새 노드를 추가하고 기존의 모든 노드에 연결하십시오.
  • 지시어 m > 1: 정도 (이웃 수)를로 나눌 수있는 모든 노드를 제거하십시오 m. 참고 0모든로 나누어 m분리 노드가 항상 제거되도록.

지시문은 빈 그래프부터 시작하여 왼쪽에서 오른쪽으로 하나씩 적용됩니다. 예를 들어 시퀀스 [0,1,0,1,0,1,3]는 다음과 같이 처리되며 멋진 ASCII 아트를 사용하여 설명됩니다. 빈 그래프로 시작하여 다음과 같이 단일 정점을 추가합니다 0.

a

그런 다음 다른 정점을 추가하고 지시에 따라 첫 번째 정점에 연결하십시오 1.

a--b

의 지시에 따라 우리는 다음 다른 연결이 끊어 정점과 연결된 하나를 추가 0하고 1:

a--b   c
 \  \ /
  `--d

우리는 0and의 지시에 따라 이것을 한 번 더 반복합니다 1.

  ,--f--e
 /  /|\
a--b | c
 \  \|/
  `--d

마지막으로, 우리는 정도-3 정점을 제거 a하고 b지시에 따라, 3:

f--e
|\
| c
|/
d

이것은 시퀀스에 의해 정의 된 그래프 [0,1,0,1,0,1,3]입니다.

입력

지시문 시퀀스를 나타내는 음이 아닌 정수 목록입니다.

산출

시퀀스에 의해 정의 된 그래프의 노드 수입니다.

테스트 사례

[] -> 0
[5] -> 0
[0,0,0,11] -> 0
[0,1,0,1,0,1,3] -> 4
[0,0,0,1,1,1] -> 6
[0,0,1,1,0,0,1,1,2,5,7,0,1] -> 6
[0,0,1,1,1,1,5,1,4,3,1,0,0,0,1,2] -> 6
[0,0,1,1,0,0,1,1,5,2,3,0,0,1,1,0,0,1,1,3,4,0,0,1,1,2,1,1] -> 8
[0,0,1,1,0,0,1,1,2,5,7,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,8] -> 14

자세한 규칙

함수 또는 전체 프로그램을 작성할 수 있습니다. 가장 짧은 바이트 수가 이깁니다. 표준 허점은 허용되지 않습니다. 답에 알고리즘을 설명하십시오.


일주일이 지났으므로 가장 짧은 대답을 받아 들였습니다. 더 짧은 것이 나중에 나오면 선택을 업데이트하겠습니다. 피터 테일러 (Peter Taylor)의 답변에 대한 언급이있다 .


5
나는 당신이 실제로 그래프를 그릴 필요가 생각하는 질문을 읽으면서 - 이것은 매우 힘든 - 스크롤 아래로,
최적화

@Optimizer 그래, 나는 그래프의 실제 표현이 중요하지 않도록 질문을 제기하고 싶었고, 지시문을 구현하는 데 주요 어려움이있을 것입니다. 노드 수는 정확성을 확인하는 쉬운 방법입니다.
Zgarb

1
나는이 도전을 정말로 좋아한다! 데이터 구조를 설계하는 것과 같습니다. 입력 및 출력 형식이 묶이지 않기 때문에 그래프를 나타내는 방법을 알아야합니다.
xnor

답변:


4

피스 , 37 31

lu?+GH<H2m@Gdf%+*@GTtTs>GTHUGQY

이 솔루션은 축소 함수 ( u)를 사용하여 목록을 작성합니다. 여기서 각 항목은 목록에 남아있는 노드에 해당하며 노드가 원래 지시문 0 또는 1에 추가되었는지 여부에 해당하는 항목 값입니다.

G는 감소 함수의 누산기 변수이며 위에서 언급 한 목록을 보유합니다. 빈 목록 인으로 초기화됩니다 Y.

HQ입력 의 각 멤버의 값을 하나씩 가져옵니다 . 식의 결과는G 매번 다음의 다음 항목이 Q에 할당되고 H식이 다시 실행됩니다.

G올바르게 업데이트하려면 지시문 0 또는 1과 다른 지시문에 대한 두 가지 가능성이 있습니다. 이 경우는 삼항으로 구별됩니다.? ... <H2 ...

경우 H0 또는 1이며, 모든 우리는 APPEND 할 필요 HG . +GH이것을 달성합니다.

그렇지 않으면 가장 먼저 필요한 것은 그래프의 모든 노드에 대해 얼마나 많은 이웃이 있는지 결정하는 것입니다. 이는 두 단계로 수행됩니다.

먼저, s>GT 입력 노드에서 또는 노드 뒤의 노드 수를 센다. 입력 노드가 1 인 경우 1을 초과한다는 점을 제외하고는 모두 입력 노드에 연결되어 있습니다.

둘째, 연결된 입력 노드보다 빠른 노드 수가 필요합니다. 입력 노드가 0이면 입력 노드는 0이고 입력 노드가 1이면 입력 노드의 인덱스입니다 T.이 값은로 지정됩니다 *@GTT. 그러나 여전히 수정해야 할 첫 번째 섹션의 초과 카운트가 있습니다. 따라서, 우리는 계산*@GTtT 입력 노드가 1 인 경우 대신 1을 뺀 값을 계산하여 입력 노드에 연결된 노드 수를 계산합니다.

% ... H 숫자는 0으로 나눌 수 있습니다. H 있으므로 제거해야하며 그렇지 않으면 0을 제공하지 않습니다.

f ... UG 따라서 제거해서는 안되는 입력의 인덱스를 제공합니다. f 필터 하고 0은 거짓입니다.

m@Gd 이 인덱스를 해당 노드의 0과 1로 변환합니다.

마지막으로, 0과 1로 레이블 된 결과 노드 목록을 찾으면 길이가 계산되고 ( l) 인쇄됩니다 (암시 적).

@PeterTaylor에게 광범위한 아이디어를 제공합니다.


12

GolfScript (53 바이트)

])~{:^1>{.-1:H)-,:T;{..H):H*T@-:T+^%!{;}*}%}{^+}if}/,

온라인 데모

나는 실제로 이것을 아직 골프화하지는 않았지만, H과 를 제거하기가 쉽지 않다는 것을 발견했다.T 변수 않으므로 로컬 최소값이 될 수 있음을 발견했습니다.

stdin에 형식으로 입력을받습니다. [0 1 2 3] . stdout에 출력을 남깁니다.

언 골프 드 :

])~{
  :^1>{
    # array of 0s and 1s
    # Each 0 has degree equal to the number of 1s after it
    # Each 1 has degree equal to the number of values before it plus the number of 1s after it
    .-1:H)-,:T;
    {
      # Stack: x
      # T' = T - x is the number of 1s after it
      # H' = H + 1 is the number of values before it
      # Degree is therefore H' * x + T' = H * x + T - x = (H-1)*x + T
      # Keep x unless degree % ^ == 0
      ..H):H*T@-:T+^%!{;}*
    }%
  }{^+}if
}/,

4

CJam, 129 75 73 68 61 46 42 바이트

Peter의 알고리즘을 기반으로 한 솔루션 :

Lq~{I+I1>{0:U(<:L{LU<,*LU):U>1b+I%},}*}fI,

따르는 코드 확장.


이전 솔루션 (61 바이트) :

Lq~{:N2<{U):UaN{f+U1$0f=+}*a+}{{:X,(N%_!{X0=L+:L;}*},Lf-}?}/,

STDIN에서 다음과 같이 입력을받습니다.

[0 0 1 1 0 0 1 1 5 2 3 0 0 1 1 0 0 1 1 3 4 0 0 1 1 2 1 1]

출력은 STDOUT의 숫자입니다.

8

알고리즘 :

  • U추가 할 노드의 id를 저장 하는 증가 변수 를 유지하십시오 .
  • , 각 목록은 목록의 첫 번째 요소로 구성된 고유 ID를 가진 노드이고 나머지 요소는 연결된 노드의 ID 인 목록의 목록을 유지하십시오.
  • 각 반복 (입력 지시문을 읽는 동안)에서
    • 지시문이 0인 경우 [U]목록 목록에 추가 하십시오.
    • 지시문이 1인 경우 U목록 목록의 각 목록에 추가 하고 각 목록 목록의 첫 번째 요소로 구성된 다른 목록을 추가하십시오.U
    • 지시문을 제거하기 위해 length - 1분할 가능한 모든 목록을 필터링하고 m해당 목록의 첫 번째 요소를 계속 주목하십시오. 필터링 후 나머지 ID 목록에서 제거 된 모든 ID를 제거합니다.

코드 확장 :

Lq~{:N2<{U):UaN{f+U1$0f=+}*a+}{{:X,(N%_!{X0=L+:L;}*},Lf-}?}/,
L                                            "Put an empty array on stack";
 q~                                          "Evaluate the input";
   {                                }/       "For each directive";
    :N                                       "Store the directive in N";
      2<{     ...    }{    ...    }?         "If directive is 0 or 1, run the first";
                                             "block, else second";
{U):UaN{f+U1$0f=+}*a+}
 U):U                                        "Increment and update U (initially 0)";
     a                                       "Wrap it in an array";
      N{         }*                          "Run this block if directive is 1";
        f+                                   "Add U to each list in list of list";
          U1$                                "Put U and list of lists on stack";
             0f=                             "Get first element of each list";
                +                            "Prepend U to the above array";
                   a+                        "Wrap in array and append to list of list";
{{:X,(N%_!{X0=L+:L;}*},Lf-}
 {                   },                      "Filter the list of list on this block";
  :X,(                                       "Get number of connections of this node";
      N%_                                    "mod with directive and copy the result";
         !{        }*                        "If the mod is 0, run this block";
           X0=                               "Get the id of this node";
              L+:L;                          "Add to variable L and update L";
                       Lf-                   "Remove all the filtered out ids from the";
                                             "remaining nodes";
,                                            "After the whole process is completed for"
                                             "all directives, take length of remaining ";
                                             "nodes in the list of list";

여기 사용해보십시오


3

Pyth, 88 80 75 자

JYFHQI!H~Y]]lY)IqH1=Y+m+dlYY]UhlY)VYI&Hq%l@YNH1~J]N))=Ymf!}TJ@YkUlYY;-lYl{J

끝났어요 다른 사람이 골프 팁을 가지고있을 수도 있습니다.

Y그래프의 인접성 목록입니다. 골프 때문에 노드가 삭제 된 후에도이 목록에 노드를 유지합니다 (그렇지 않으면 모든 인덱스를 업데이트해야합니다). 각 노드는 인접 노드로 존재합니다. 목록 J은 삭제 된 노드를 추적합니다.

예제 입력에서 인접 목록의 변경 사항을 보여줍니다 [0,1,0,1,0,1,3].

입력 0 : Y = [[0]] J = []
입력 1 : Y = [[0,1], [0,1]] 0 J = []
입력 0 : Y = [[0,1], [0,1], [2]] J = []
입력 1 : Y = [[0,1,3], [0,1,3], [2,3], [0,1,2,3]] J = []
입력 0 : Y = [[0,1,3], [0,1,3], [2,3], [0,1,2,3], [4]] J = []
입력 1 : Y = [[0,1,3,5], [0,1,3,5], [2,3,5], [0,1,2,3,5], [4,5 ], [0,1,2,3,4,5]] J = []
입력 3 : Y = [[3,5], [3,5], [2,3,5], [2,3,5], [4,5], [2,3,4,5]] J = [0,1]

그런 다음 알고리즘은 매우 간단합니다. input == 0 인 경우 모든 입력을 반복합니다. input == 1 인 경우 자체 노드를 사용하여 새 노드를 추가합니다. 모든 노드를 이웃 노드 (삭제 된 노드)로 추가하고 새 노드를 추가합니다. input> 1 인 경우 모든 노드의 인접 목록으로이 노드 : # neighbor-1 % input == 0 인 노드를 결정하고 각 노드를에 추가하여 J각 경우에를 사용하여 각 노드의 이웃을 업데이트하십시오 J. 마지막 Y에 길이에서 (세트) 의 길이를 뺀 값을 인쇄하십시오 J.

JYFHQI!H~Y]]lY)IqH1=Y+m+dlYY]UhlY)VYI&Hq%l@YNH1~J]N))=Ymf!}TJ@YkUlYY;-lYl{J
JY                      set J=[]
  FHQ                   for H in: input()
I!H      )                if H==0:
   ~Y]]lY                   Y.append([len(Y)])
IqH1              )       if H==1:
    =Y+                     Y=                 +
       m+dlYY                 old nodes updated
             ]UhlY                              new node with all neighbors
VY                )       for N in range(len(Q)):
  I&Hq%l@YNH1    )          if H>0 and len(Y[N])%H==1:
             ~J]N             J.append(N) //this node gets deleted
=Ym           Y           Y=[           for k in Y]
   f!}TJ@YkUlY               k-filtered  //all items of J are removed
;                       end input for loop
-lYl{J                  print len(Y) - len(set(J))

용법

스크립트를 호출하고 입력 [0,1,0,1,0,1,3]또는 다른 테스트 사례를 제공하십시오.


3

2

파이썬 2, 296

s=input();e=[];n=[];c=0
for t in s:
    if t<2:e=e+[[]]if t==0 else [x+[c]for x in e]+[n[:]];n+=[c];c+=1
    else:
        M=zip(*[(i,n[i])for i,x in enumerate(e)if not len(x)%t])
        if M:e=[list(set(z)-set(M[1]))for j,z in enumerate(e)if j not in M[0]];n=list(set(n)-set(M[1]))
print len(n)

각 노드에는 고유 한 ID가 부여되고 각 노드의 인접 ID가 기록됩니다. 지시문이 0이면 비어있는 이웃 목록이 새 노드에 추가됩니다. 지시문이 1이면 모든 기존 노드의 ID가 새 노드의 이웃 목록이되고 다른 모든 이웃 목록이 새 노드 ID를 포함하도록 업데이트됩니다. m> 1의 경우, m의 배수 인 이웃 목록을 가진 노드는 노드 목록과 모든 이웃 목록에서 제거됩니다. 이전 버전에서 버그를 발견 한 @Optimizer에게 감사드립니다.


2

넷 로고, 160

to f[t]foreach t[if ? = 0[crt 1]if ? = 1[crt 1[create-links-with other turtles]]if ? > 1[ask turtles with[count my-links mod ? = 0][die]]]show count turtles
end

각 기호를 읽고 적절한 조치를 수행하여 구현이 간단합니다.

to f[t]
  foreach t [
    if ? = 0 [
      crt 1
    ]
    if ? = 1 [
      crt 1 [create-links-with other turtles]
    ]
    if ? > 1 [
      ask turtles with [count my-links mod ? = 0] [die]
    ]
  ]
  show count turtles
end

명령 줄에서 다음과 같이 실행할 수 있습니다 f[0 0 1 1 0 0 1 1 2 5 7 0 1].


2

루비 159157 ( 데모 )

N=Struct.new:l
G=->c{n=[]
c.map{|m|m<1?n<<N.new([]):m<2?(w=N.new([])
n.map{|x|x.l<<w;w.l<<x}
n<<w):(n-=r=n.select{|x|x.l.size%m<1}
n.map{|x|x.l-=r})}
n.size}

Gstabby-lambda 구문을 사용하여 호출되는 함수를 정의 합니다. G[[0, 1]]명령 0과 로 호출하는 데 사용하십시오 1.

구현은 매우 간단 합니다. 속성을 통해 연결된 모든 노드에 대한 참조를 보유 하는 Node구조 ( N위에 불림 )가 있습니다 l. G필요에 따라 노드를 작성하고 해당 링크를 조작합니다. 읽을 수있는 버전은 여기에 있습니다 .


1

CJam, 99 97 바이트

Lal~{I2<{_0={{If+z}2*));0+a+}{;Iaa}?}{_0=!!{{{_:+I%+}%z}2*));1+a+{{W=},z}2*);z_{);}{a}?}*}?}fI0=,

아직 골프를 많이 치러야합니다. 알고리즘은 인접 행렬을 추적하는 것을 기반으로하지만 특별히 처리하지 않고 빈 행렬을 나타내는 것은 나에게 두통을줍니다.

여기에서 테스트하십시오.

입력은 CJam 스타일 배열입니다.

[0 0 1 1 0 0 1 1 2 5 7 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 8]

이 테스트 하니스를 사용하여 모든 테스트를 실행할 수 있습니다.

"[]
[5]
[0,0,0,11]
[0,1,0,1,0,1,3]
[0,0,0,1,1,1]
[0,0,1,1,0,0,1,1,2,5,7,0,1]
[0,0,1,1,1,1,5,1,4,3,1,0,0,0,1,2]
[0,0,1,1,0,0,1,1,5,2,3,0,0,1,1,0,0,1,1,3,4,0,0,1,1,2,1,1]
[0,0,1,1,0,0,1,1,2,5,7,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,8]"

","SerN/{
La\~{I2<{_0={{If+z}2*));0+a+}{;Iaa}?}{_0=!!{{{_:+I%+}%z}2*));1+a+{{W=},z}2*);z_{);}{a}?}*}?}fI0=,
N}/

1

파이썬 2, 174

l=input()
g={}
n=0
for x in l:
 n+=1;g[n]=set()
 if x>1:h={i for i in g if len(g[i])%x};g={i:g[i]&h for i in set(g)&h}
 if x==1:
  for i in g:g[i]^={n};g[n]^={i}
print len(g)

이것은 여전히 ​​많은 골프를 치고있을 수 있습니다.

나는 사전을 사용했다 g그래프를 나타 내기 위해 을 . 노드에는 숫자로 레이블이 지정되며 인접한 노드 세트에 맵핑됩니다. 즉, 에지의 각 업데이트는 양쪽 끝점에서 모두 실행되어야합니다.

새로운 노드 인덱스는 카운트 업하여 생성됩니다 n. 매번 새로운 빈 노드를 만듭니다 n. command의 0경우에는 그대로 남아 있습니다. 명령의 1경우 g[i]^={n};g[n]^={i}; 를 통해 서로 노드에 연결됩니다 . xor를 사용하여 노드가 자체적으로 연결되지 않도록합니다. > 1 명령의 경우 즉시 삭제됩니다.

정도가 배수 인 노드의 필터링은 먼저 나머지 노드 ( h)를 찾은 다음 and노드 목록과 각 노드의 이웃 노드를 사용하여 필터링 합니다.

마지막으로 그래프 사전의 항목 수가 답입니다.


0

수학, 223 바이트

와우, 이것은 내가 예상했던 것보다 길었다.

f=(g={};t=Append;l=Length;m=ListQ;h=Flatten;k=Position;o=If;(d=#;o[d==0,g=g~t~{},o[d==1,g=o[m@#,t[#,l@g+1],#]&/@g;g=t[g,h@k[g,_?m,1]],g=o[l@#~Mod~d==0,0,#]&/@g;p=h@k[g,0];(c=#;g=#~DeleteCases~c&/@g)&/@p]])&/@#;g~Count~_?m)&

용법:

f@{0, 1, 0, 1, 0, 1, 3}

테스트 사례의 결과는 다음과 같습니다.

f /@ {
  {},
  {5},
  {0, 0, 0, 11},
  {0, 1, 0, 1, 0, 1, 3},
  {0, 0, 0, 1, 1, 1},
  {0, 0, 1, 1, 0, 0, 1, 1, 2, 5, 7, 0, 1},
  {0, 0, 1, 1, 1, 1, 5, 1, 4, 3, 1, 0, 0, 0, 1, 2},
  {0, 0, 1, 1, 0, 0, 1, 1, 5, 2, 3, 0, 0, 1, 1, 0, 0, 1, 1, 3, 4, 0, 0, 1, 1, 2, 1, 1},
  {0, 0, 1, 1, 0, 0, 1, 1, 2, 5, 7, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 8}
}

Out: {0, 0, 0, 4, 6, 6, 6, 8, 14}

덜 골프 :

f = (
   a = #;
   g = {};
   Table[
    If[a[[n]] == 0,
     AppendTo[g, {}],
     If[a[[n]] == 1,
      g = If[ListQ@#, Append[#, Length@g + 1], #] & /@ g; 
      g = Append[g, Flatten@Position[g, _?ListQ, 1]],
      If[a[[n]] > 1,
       g = If[Mod[Length@#, a[[n]]] == 0, 0, #] & /@ g;
       p = Flatten@Position[g, 0];
       (c = #; g = DeleteCases[#, c] & /@ g) & /@ p
       ]
      ]
     ],
    {n, Length@a}];
   Count[g, _?ListQ]
   ) &

이것이 작동하는 방식은 그래프를 "이웃 목록"목록으로 나타내는 것입니다.
를 들어 0 지시어, 난 그냥 빈 목록을 추가합니다.
를 들어 1 지시자, 나는 이전의 모든 노드의 목록을 추가하고, 이전의 모든 노드에 새 노드를 추가 할 수 있습니다.
지시문 > 1 의 경우 지정된 노드를 제거하고 나머지를 업데이트했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.