2017-10-01 3 views
2

세 가지 다른 이름의 무작위 목록을 생성하는 술어 randomnames/1을 작성하려고합니다.프롤로그에서 중복되지 않고 특정 길이의 무작위 목록을 만드는 방법은 무엇입니까?

random_names([A,B,C]) :- 
    random_name(A), 
    random_name(B), 
    random_name(C). 

이 유일한 문제는 : 사람이 어떻게해야 제안,

name(1, Mary). 
name(2, Pat). 
name(3, James). 
name(4, Bob). 
name(5, Susan). 

random_name(Name):- 
    random(0, 6, N),  
    name(N, Name). 

이 목록의 내용 : 이름은 데이터베이스에있는 나는 이미 임의의 이름에 대한 조건이 생성 된 목록에서 중복을 얻을 수 있습니다. 나는 그 문제를 해결하는 방법을 알아낼 수 없다. 중복을 제거하기위한 새로운 술어를 작성할 수는 있지만, 복제본을 다른 변수로 대체하면 어떻게 목록에 여전히 세 가지 요소가 있습니까? 그리고 random_names 술어에 명확한 머리와 꼬리가 없을 때 어떻게 제거 술어를 작성합니까?

답변

3

프롤로그에서 프로그래밍 할 때는 조건으로 솔루션에서 만족해야한다고 생각하십시오.

현재 세 가지 요소가있는 목록을 설명하는 방법을 이미 알아 냈습니다. 각 요소는 임의의 이름입니다.

좋은 시작이지만 아직 충분하지 않습니다. 외에도 요소가 쌍으로 구분된다는 조건을 설명하고자합니다.

그래서 을 설명합니다. 모든 요소가 쌍으로 구분되는 세 가지 요소의 목록입니다.

나는 소리 방식으로 용어의 disequality을 표현하는 dif/2를 사용하여, 당신에게 출발을 ( 참조)

 
three_distinct_elements([A,B,C]) :- 
     dif(A, B), 
     dif(A, C), 
     dif(B, C). 

당신은 목록이를 설명하는 더 일반적인 더 우아한 방법을 찾을 수 있습니다 3 개 이상의   요소가 있습니다. 그러나 위의 내용은 당면 과제를 해결하기에 충분합니다.

그래서, 그것은 단지 예를 들어 사용 당신이 이미 가지고있는 조건을 결합 에 남아 :

 
three_distinct_random_names(Ls) :- 
     random_names(Ls), 
     three_distinct_elements(Ls). 

이것은 단순히 당신이 이미 구현 한 조건의 함께입니다. 전체적으로,이 술어의 해답은 당신이 원하는 것을 줄 것입니다 : 3 개의 별개의 임의의 이름을 가진 목록.

그러나, 술어는 (운동 : ?) 실패 할 수 있습니다. 이 솔루션을 찾을 때까지

예를 repeat/0 사용, 술어 을 시도하려면

 
?- repeat, three_distinct_random_names(Ls). 

는이 문제를 해결하기 위해 더 나은 방법이 있습니다. 그러나, 첫 번째 근사치로, 좋은 조건 인 빌딩 블록에 집중할 것을 권장합니다.

나는 당신이 무엇을 쓰기에 대한 총평이 있습니다,

내가 중복 제거 위한 새로운 술어를 쓸 수 있지만, 어떻게 다른 변수와 중복 다음을 대체 것을 목록 있도록 여전히 세 가지 요소가 있습니까?

이 모두 매우 이 불가피이 모호하게됩니다 : 당신은 프롤로그를 최대한 활용하기 위해 등 "대체", "제거"여기에 대해 생각 가에 대한를 유지해야 조건을 설명 에 초점 당신이 찾고 싶은 솔루션!

중복되지 않은 목록을 찾고 싶습니까? 설명 그러한 목록은 무엇이 보일 것입니까  은 좋아합니다. 임의의 이름을 원하십니까? 같은 이름이 어떻게 생겼는지 설명하십시오.

+0

너무 감사 randseq/3이 목록에 남아있는 모든 생성받은 후 N. 1에서 범위의 모든 고유 한 임의의 숫자의 목록을 생성은 이름에 매핑 번호입니다 당신의 정교한 답변에 많이! 술어가 실패 할 수있는 이유는 실제로 중복이 발견되면'dif' 중 하나가 실패하고'three_distinct_elements'가 실패한 다음 전체 술어가 실패한다는 것입니다. 그게 맞습니까? –

+0

네, 맞습니다! – mat

+0

코드를 사용하여 실패하지 않는 답변을 하나만 얻을 수 있다고 생각하십니까? 이 술어가 다른 술어의 일부로 필요하기 때문에 쿼리에서'repeat '를 할 수 없습니다. 코드에'repeat'를 추가하면 많은 양의 후퇴 (backtracking) 결과를 얻을 수 있으며'컷 (cut) '을 추가하면'반복 (repeat)'을 무효화하는 것처럼 보입니다. 반복과 절단을 모두 할 수 있습니까? –

0

Swi-Prolog를 사용하는 경우 Swi와 함께 제공되는 매우 편리한 randseq/3 술어를 사용할 수 있습니다.

name(1, 'Mary'). 
name(2, 'Pat'). 
name(3, 'James'). 
name(4, 'Bob'). 
name(5, 'Susan'). 

random_names(Names, Count) :- 
    % 5 is the amount of names available in database 
    randseq(Count, 5, L), 
    maplist(name, L, Names). 

사용 예 :

?- random_names(Names, 3). 
Names = ['Mary', 'James', 'Susan']. 

?- random_names(Names, 5). 
Names = ['Susan', 'Bob', 'James', 'Mary', 'Pat']. 
관련 문제