반음계 수 구하기


13

놀랍게도 아직 그래프 채색에 대한 도전은 없었습니다!

방향이없는 그래프가 주어지면 인접한 정점 두 개가 같은 색을 공유하지 않도록 각 정점에 색을 지정할 수 있습니다. 이를 달성하는 데 필요한 가장 작은 별개의 색 χ 를 그래프 의 색수 라고합니다 .

예를 들어, 다음은 최소 색상 수를 사용하는 유효한 색상을 보여줍니다.

(위키 백과에서 발견)

따라서이 그래프의 색도는 χ = 3 입니다.

많은 정점 N <16 ( 1 에서 N 까지 번호가 매겨 짐 )과 모서리 목록이 주어지면 그래프의 색도를 결정 하는 프로그램이나 함수를 작성하십시오 .

입력이 사전 처리되지 않는 한 입력을 받고 편리한 형식으로 출력 할 수 있습니다. 즉, 문자열이나 배열을 사용하거나 문자열에 편리한 구분 기호를 추가하거나 중첩 배열을 사용할 수 있지만, 평평한 구조에는 아래 예제와 동일한 숫자가 동일한 순서로 포함되어야합니다.

내장 된 그래프 이론 관련 기능 (예 : Mathematica 's ChromaticNumber)을 사용할 수 없습니다 .

그래프에 색상이 지정되지 않도록 그래프에 루프 (정점과 자체를 연결하는 가장자리)가 없다고 가정 할 수 있습니다.

이것은 코드 골프이며, 가장 짧은 대답 (바이트)이 이깁니다.

당신의 프로그램은 적어도이 모든 것들을 적당한 시간 안에 해결해야합니다. (모든 입력을 올바르게 해결해야하지만 더 큰 입력의 경우 더 오래 걸릴 수 있습니다.)

게시물을 줄이려면 다음 예에서 가장자리를 쉼표로 구분 된 단일 목록으로 표시합니다. 원하는 경우 줄 바꿈을 사용하거나 편리한 배열 형식으로 입력을 예상 할 수 있습니다.

삼각형 (χ = 3)

3
1 2, 2 3, 1 3

6 개의 정점의 "링" (χ = 2)

6
1 2, 2 3, 3 4, 4 5, 5 6, 6 1

5 개의 정점의 "링" (χ = 3)

5
1 2, 2 3, 3 4, 4 5, 5 1

위의 사진 예 (χ = 3)

6
1 2, 2 3, 3 4, 4 5, 5 6, 6 1, 1 3, 2 4, 3 5, 4 6, 5 1, 6 2

7 개의 정점에 대한 위의 일반화 (χ = 4)

7
1 2, 2 3, 3 4, 4 5, 5 6, 6 7, 7 1, 1 3, 2 4, 3 5, 4 6, 5 7, 6 1, 7 2

피터슨 그래프 (χ = 3)

10
1 2, 2 3, 3 4, 4 5, 5 1, 1 6, 2 7, 3 8, 4 9, 5 10, 6 8, 7 9, 8 10, 9 6, 10 7

5 개의 정점과 연결이 끊긴 정점의 전체 그래프 (χ = 5)

6
1 2, 1 3, 1 4, 1 5, 2 3, 2 4, 2 5, 3 4, 3 5, 4 5

8 개의 정점의 완전한 그래프 (χ = 8)

8
1 2, 1 3, 1 4, 1 5, 1 6, 1 7, 1 8, 2 3, 2 4, 2 5, 2 6, 2 7, 2 8, 3 4, 3 5, 3 6, 3 7, 3 8, 4 5, 4 6, 4 7, 4 8, 5 6, 5 7, 5 8, 6 7, 6 8, 7 8

15 개의 정점이있는 삼각형 격자 (χ = 3)

15
1 2, 1 3, 2 3, 2 4, 2 5, 3 5, 3 6, 4 5, 5 6, 4 7, 4 8, 5 8, 5 9, 6 9, 6 10, 7 8, 8 9, 9 10, 7 11, 7 12, 8 12, 8 13, 9 13, 9 14, 10 14, 10 15, 11 12, 12 13, 13 14, 14 15

합리적으로 정의 할 수 있습니까? 1 분? 10?
ThreeFx

@ThreeFx 예, 10 분이 합리적입니다. 반나절은 그렇지 않습니다. 나는 한계에 너무 엄격한 것을 원하지 않습니다. 왜냐하면 동일한 (내) 컴퓨터에서 모든 것을 다시 테스트해야하기 때문입니다. 그러나 컴퓨터에서 한 시간 안에 완료되면 괜찮습니다.
Martin Ender

답변:


4

파이썬 2.7 - 122 109 111 109 108 103

f=lambda n,e,m=1:any(all(t*m//m**a%m!=t*m//m**b%m for(a,b)in e)for t in range(m**n))and m or f(n,e,m+1)

용법:

print f(5, [(1, 2), (2, 3), (3, 4), (4, 5), (5, 1)])

색수 (m)를 증가시켜 무차별 강제력을 발휘하고 가능한 모든 채색을 확인하십시오. 하나의 착색은 기본 m의 숫자로 설명 될 수 있습니다. 따라서 가능한 착색은 0, 1, ..., m ^ n-1입니다.

편집 : 8 정점의 완전한 그래프는 꽤 오래 걸립니다. 그러나 내 노트북은 약 10 분 안에 해결합니다. 다른 테스트 사례는 몇 초 밖에 걸리지 않습니다.


편집 2 : 전처리가 허용된다는 것을 읽으므로 정점의 색인을 0으로 시작하십시오. 람다를 녹이고 m을 함수 매개 변수에 넣습니다 (-11).


편집 3 : 전처리는 허용 되지 않습니다-> t * m (+4)로 돌아가고, //에서 / (-2)로 단순화되었습니다.


편집 4 : xnor 덕분에 (-2)에서 대괄호를 제거하십시오.


편집 5 : 모듈로 m을 두 번 사용하는 대신 간단히 빼고 모듈로 (-1)을 사용하십시오. 이것은 또한 상당히 성능 향상입니다. 모든 테스트 케이스는 랩톱에서 약 25 초가 걸립니다.


편집 6 : 1과 m + = 1 (-5) 대신 재귀 호출 다시 한번 감사합니다, xnor.


좋은 방법입니다. 간단한 골프 : 당신이 추가 인수로 그들을 오해하지 않도록 in parens (간격으로 인해 여기에 문자가 없음) all([...])를 넣으면 괄호를 제거 할 수 있습니다 . 또한 while 루프를 사용하지 않고 함수 호출로 다음 최고 수준으로 재귀를 수행하면 문자를 저장할 수 있다고 생각합니다 . a,ballm
xnor

고맙게도 재귀 적 접근에는 +2 문자가 필요합니다. 범위 (n + 1) 접근에서 m에 대한 A도.
Jakube

재귀 적 접근 방식 anyand/or트릭을 약간 최적화 한 다음 몇 가지 문자를 저장합니다 f=lambda n,e,m=1:any(all(t*m//m**a%m!=t*m//m**b%m for(a,b)in e)for t in range(m**n))and m or f(n,e,m+1).
xnor

2

자바 - 241 (218)

int k,j,c;int f(int n,int[]e){for(k=1;k<=n;k++)for(long p=0;p<x(n);p++){for(j=0,c=0;j<e.length;c=p%x(e[j])/x(e[j]-1)==p%x(e[j+1])/x(e[j+1]-1)?1:c,j+=2);if(c<1)return k;}return 0;}int x(int a){return(int)Math.pow(k,a);}

제약 조건이 주어진 경우 가장 확실한 방법은 무차별 대입입니다. 각 색수를 단계별로 살펴보고 각 k색을 각 정점에 할당하십시오. 같은 색의 이웃이 없으면 번호가 있습니다. 그렇지 않으면 따라 이동하십시오.

χ = 8(완전한 그래프는 여기에서 빨라집니다) 의 테스트 케이스에는 가장 오래 걸리지 만 여전히 15 초 미만입니다 (최근 편집시 약 100 초).

입력 값은 꼭짓점 수 ne[]OP 쉼표로 구분 된 값과 동일한 순서로 제공된 가장자리 꼭짓점의 배열입니다 .

줄 바꿈으로 :

int k,j,c;
int f(int n,int[]e){
    for(k=1;k<=n;k++)
        for(long p=0;p<x(n);p++){
            for(j=0,c=0;
                j<e.length;
                c=p%x(e[j])/x(e[j]-1)==p%x(e[j+1])/x(e[j+1]-1)?1:c,
                j+=2);
            if(c<1)return k;
        }
    return 0;
}
int x(int a){return(int)Math.pow(k,a);}

아, 그리고 이것은 입력이 일종의 채색 가능한 그래프라고 가정합니다. 가장자리가 v1에서 v1로 반복되거나 꼭짓점이 없으면 색을 칠할 수없고 0을 출력합니다 χ=1. 가장자리가없는 그래프에는 계속 작동합니다 .


2

파이썬 3-162

동일한 무차별 접근 방식을 사용하지만, 더 빠른 조합 생성을 위해 itertools 라이브러리를 사용합니다. 상당히 평범한 기계에서 1 분 안에 완전한 8- 그래프를 해결합니다.

import itertools as I
def c(n,v):
 for i in range(1,n+1):
  for p in I.product(range(i),repeat=n):
   if(0==len([x for x in v if(p[x[0]]==p[x[1]])])):return i

완전한 8 그래프 케이스의 사용 예 :

print(c(8,[x for x in I.combinations(range(8), 2)]))

1

하스켈, 163 바이트

p x=f(length x)(transpose x)1
f a[b,c]d|or$map(\x->and$g x(h b)(h c))(sequence$replicate a[1..d])=d|0<1=f a b c(d+1)
g a=zipWith(\x y->a!!x/=a!!y)
h=map(flip(-)1)

사용법은 다음과 같습니다.

p [[1, 2],[2, 3],[3, 1]]

기본 무차별 접근 방식. 유효한 모든 착색 조합을 확인하십시오. 나는 이것을 더 짧게하는 데 도움이되는 팁을 듣고 행복하다는 것을 제외하고는 여기에 말할 것이 많지 않습니다.)


정점을 감소시키고 바꾸는 것은 "전처리"로 간주됩니다. "모든 편리한 형식"에서 염두에 둔 것은 플랫 목록, 중첩 목록, 문자열, 편리한 구분 기호가있는 문자열 등 중에서 선택할 수 있다는 것이지만 플랫 구조는 도전 과제에 지정된 것과 동일해야합니다.
Martin Ender

@ MartinBüttner 좋아, 내가 바꿀거야
ThreeFx

@ThreeFx는 all id것과 동일하다 and, any id동일하다 orany id$map f list마찬가지로 동일하다 any f list. 또한, 당신과 함께 몇 가지를 할 수있는 g: 당신은 그것을 다시 정의 할 수 있습니다 g a=(and.).zipWith(\x y->a!!x/=a!!y), 그것은 중위하게 대체 할 수있는 입력 순서 변경 (\x->g x b c)으로 g b c또는 완전히 지점이없는 수 있도록하고 인라인을. 이들 중 일부는 그래서 그들 모두를 시도, 함께 일을하고 최고의 하나 : 선택하지 않은
자랑 haskeller

1
@ MartinBüttner 나는 그것이 maaaaany 바이트의 비용으로 고정되어 있다고 생각합니다. : D
ThreeFx

1
입력에 꼭짓점 수없이 일곱 번째 예를 어떻게 해결합니까?
Martin Ender
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.