2009년 10월 9일 금요일

C++로 풀어본 아인슈타인의 퍼즐

아인슈타인의 퍼즐이란 것이 있다.
각기 다른 다섯 채의 집에 사는 사람들에 관한 퍼즐(정확히는 수수께끼)이다.

아인슈타인이 "2%의 사람만이 이 퍼즐을 풀 수 있을 것"이라 했다는 얘기도 있는데, 뻥일 뿐이다.
사실, 아인슈타인이 이 퍼즐을 만든 사람인지도 확실하지 않다.

이 퍼즐엔 다양한 종류의 변종이 있긴 하지만, 골자는 동일하다.
서로 다른 색깔의 다섯 채의 집에 사는 각기 다른 국적의 사람이 살며, 서로 다른 동물을 기르고, 서로 다른 음료를 좋아하며, 서로 다른 담배를 핀다.
이 때 주어진 조건을 보고 누가 물고기를 기르는가를 맞추는 것이다.

5 Houses were built on one side of a small street, each painted in another color.
The houses were sold to 5 single persons, each person has another nationality.
Each of the 5 house owners prefers another drink and another type of cigarettes.
A pet is living in each house, but also they are all different.

One of the pets is a fish. Because the fish is so beautiful, everybody wants to see the fish.
But who of the 5 persons is the owner of the beautiful fish?
You can find out.


The Englishman lives in the red house.
The Swede keeps dogs.
The Norwegian lives in the first of the street.
The German drinks tea.
The Portuguese smokes Camel.

The green house is located on the left side of the white one.
The owner of the green house drinks coffee.
The owner of the yellow house smokes Dunhill.
The man, who has a cat, is living next to the man smokes Malboro.
The Norwegian lives next to the blue house.
The man in the center house drinks milk.
The man who keeps horses lives next to the Dunhill smoker.
The Malboro smoker has a neighbor who drinks water.

The Pall Mall smoker keeps birds.
The Lucky Strike smoker prefers beer.


해석 보기..


풀이 순서는 아래와 같다.

1. 국적, 집의 색깔, 애완동물, 음료, 담배를 숫자로 지정 (0~4)
2. 각 요소의 모든 조합를 배열에 저장 (5! = 120이므로 각기 120가지 상황이 가능)
3. 매 경우를 조건과 비교하여 조건에 맞으면 결과 출력


1. 각 조건을 숫자로 지정

#define ENGLISHMAN 0
#define SWEDE 1
#define NORWEGIAN 2
#define GERMAN 3
#define PORTUGESE 4

#define RED 0
#define GREEN 1
#define YELLOW 2
#define WHITE 3
#define BLUE 4

#define DOG 0
#define CAT 1
#define BIRD 2
#define FISH 3
#define HORSE 4

#define BEER 0
#define TEA 1
#define COFFEE 2
#define MILK 3
#define WATER 4

#define LSTRIKE 0
#define PMALL 1
#define CAMEL 2
#define DUNHILL 3
#define MALBORO 4


2. 5!(==120) 개의 조합 생성

int fillComposionTable(int five[][5])
{
    //five[120][5]에 모든 조합을 채우기
    //리턴값은 조합의 갯수(5!=120)
    int iPos = 0;

    for (int a=0; a<5; a++)
    {
        for (int b=0; b<5; b++)
        {
            if (a==b) continue;
            for (int c=0; c<5; c++)
            {
                if (a==c || b==c) continue;
                for (int d=0; d<5; d++)
                {
                    if (a==d || b==d || c==d) continue;
                    five[iPos][0] = a;
                    five[iPos][1] = b;
                    five[iPos][2] = c;
                    five[iPos][3] = d;
                    //a, b, c, d가 나오면 마지막 e는 계산할 필요 없음
                    //0+1+2+3+4 == 10
                    five[iPos++][4] = 10-(a+b+c+d);
                }
            }
        }
    }

    return iPos;
}


3. 조합이 조건에 맞는지 확인

bool CheckStatus(int *Color, int *Nationality, int *Pet, int *Drink, int *Cigarette)
{
    if (Nationality[ENGLISHMAN] != Color[RED]) return false;
    if (Nationality[SWEDE] != Pet[DOG]) return false;
    if (Nationality[NORWEGIAN] != 0) return false;
    if (Nationality[GERMAN] != Drink[TEA]) return false;
    if (Nationality[PORTUGESE] != Cigarette[CAMEL]) return false;

    if (Color[GREEN] - Color[WHITE] != -1) return false;
    if (Color[GREEN] != Drink[COFFEE]) return false;
    if (Color[YELLOW] != Cigarette[DUNHILL]) return false;
    int diff = Pet[CAT] - Cigarette[MALBORO];
    if (diff != -1 && diff != 1) return false;
    diff = Nationality[NORWEGIAN] - Color[BLUE];
    if (diff != -1 && diff != 1) return false;
    if (Drink[MILK] != 2) return false;
    diff = Pet[HORSE] - Cigarette[DUNHILL];
    if (diff != -1 && diff != 1) return false;
    diff = Cigarette[MALBORO] - Drink[WATER];
    if (diff != -1 && diff != 1) return false;

    if (Cigarette[PMALL] != Pet[BIRD]) return false;
    if (Cigarette[LSTRIKE] != Drink[BEER]) return false;

    return true;
}


4. (조건에 맞는 경우) 화면 출력

void PrintOutStatus(int *Color, int *Nationality, int *Pet, int *Drink, int *Cigarette)
{
    printf("\n");
    int Color_[5], Nationality_[5], Pet_[5], Drink_[5], Cigarette_[5];
    for (int i=0; i<5; i++)
    {
        Color_[Color[i]] = i;
        Nationality_[Nationality[i]] = i;
        Pet_[Pet[i]] = i;
        Drink_[Drink[i]] = i;
        Cigarette_[Cigarette[i]] = i;
    }

    for (int j=0; j<5; j++)
    {
        printf("house #%d: ", j+1);

        switch (Color_[j])
        {
        case 0:
            printf("Red,    ");
            break;
        case 1:
            printf("Green,  ");
            break;
        case 2:
            printf("Yellow, ");
            break;
        case 3:
            printf("White,  ");
            break;
        case 4:
            printf("Blue,   ");
            break;
        }
   
        switch (Nationality_[j])
        {
        case 0:
            printf("Englishman, ");
            break;
        case 1:
            printf("Swede,      ");
            break;
        case 2:
            printf("Norwegian,  ");
            break;
        case 3:
            printf("German,     ");
            break;
        case 4:
            printf("Portugese,  ");
            break;
        }

        switch (Pet_[j])
        {
        case 0:
            printf("Dog,   ");
            break;
        case 1:
            printf("Cat,   ");
            break;
        case 2:
            printf("Bird,  ");
            break;
        case 3:
            printf("Fish,  ");
            break;
        case 4:
            printf("Horse, ");
            break;
        }

        switch (Drink_[j])
        {
        case 0:
            printf("Beer,   ");
            break;
        case 1:
            printf("Tea,    ");
            break;
        case 2:
            printf("Coffee, ");
            break;
        case 3:
            printf("Milk,   ");
            break;
        case 4:
            printf("Water,  ");
            break;
        }

        switch (Cigarette_[j])
        {
        case 0:
            printf("Lucky Strike\n");
            break;
        case 1:
            printf("Pall Mall\n");
            break;
        case 2:
            printf("Camel\n");
            break;
        case 3:
            printf("Dunhill\n");
            break;
        case 4:
            printf("Malboro\n");
            break;
        }
    }

    printf("So, the owner of the fish is the ");
    switch (Nationality_[Pet[FISH]])
    {
    case 0:
        printf("Englishman");
        break;
    case 1:
        printf("Swede");
        break;
    case 2:
        printf("Norwegian");
        break;
    case 3:
        printf("German");
        break;
    case 4:
        printf("Portugese");
        break;
        }
    printf("\n\n");
}


5. main() 함수

int main(int argc, char* argv[])
{
    int five[120][5];

    printf("constructing Composition table...\n");
    fillComposionTable(five);

    int *Color, *Nationality, *Pet, *Drink, *Cigarette;

    for (int a=0; a<120; a++)
    {
        if ((a & 3) == 0) printf("calculating %3d of %3d (%6.2f%%)...\n", a+4, 120, (a+4)/120.0*100);
        Color = five[a];
        for (int b=0; b<120; b++)
        {
            Nationality = five[b];
            for (int c=0; c<120; c++)
            {
                Pet = five[c];
                for (int d=0; d<120; d++)
                {
                    Drink = five[d];
                    for (int e=0; e<120; e++)
                    {
                        Cigarette = five[e];
                       
                        if (CheckStatus(Color, Nationality, Pet, Drink, Cigarette))
                            PrintOutStatus(Color, Nationality, Pet, Drink, Cigarette);
                    }
                }
            }
        }
    }

    return 0;
}


6. 실행결과

실행결과 및 답 보기..



참 쉽죠잉~?

참고로, 노트북(Core2Duo T9500@2.6GHz)에서 돌려보니 전 루프를 다 도는데 172.672초(약 3분) 걸렸다.

댓글 46개:

  1. C++로... 반칙이라능ㅋㅋㅋ

    답글삭제
  2. 도구사용금지 라고 안했으므로 유효?

    답글삭제
  3. ver.2 로는 이제 유전자 알고리즘이나, 휴리스틱이나 퍼지를 적용해서 (응?)

    그냥 98%에 속하기를 선택하렵니다 ㅋㅋ





    아차! 오늘은 한글날입니다

    답글삭제
  4. @okto - 2009/10/09 08:12
    이게 왜 반칙이냐능.

    촛불집회 불법선언이랑 비슷한 것 같다능.



    혹 이가카 끄나풀 아니시냐능.

    답글삭제
  5. @zasfe - 2009/10/09 09:17
    감사드릴 뿐... ㅎㅎ

    답글삭제
  6. @구차니 - 2009/10/09 09:53
    좋은 생각이군요.



    퍼지 알고리즘으로 하나 만들어 트랙백 좀... (굽신굽신)

    답글삭제
  7. 뭐지...-_-;;; 그런데.. 귀국 했는감?

    답글삭제
  8. @Oo고목나무oO - 2009/10/09 23:37
    아냐, 한 주 남았어...

    귀국 하면 보자.



    네 선물은 런던까지 가서 샀다. ㅎㅎ

    답글삭제
  9. @BLUEnLIVE - 2009/10/09 23:44
    오호호.. 런던표 배뚜맨 가면인가...ㅋㅋㅋ



    헛.. 혹시 명품가방? ㅋㅋㅋ

    답글삭제
  10. @BLUEnLIVE - 2009/10/09 22:55
    그당시에 C++같은게 있었을리 없다능!!

    답글삭제
  11. @okto - 2009/10/09 08:12
    C++가 없었는데, C++로 문제를 푼 게 왜 반칙이냐능.



    기독경 나올 때 담배가 없었는데, 기독교도들 담배 피지 말란 얘기랑 비슷한 거 아니냐능. ㅋㅋ

    답글삭제
  12. 프로그래밍으로 푸는 것은 퍼즐에 대한 예의가 아닙니다. 머리로 풀어야죠. 방금 풀어봤는데 정답은 포르투갈인이군요.

    답글삭제
  13. P 수준 문제인데... 이 무슨 괴상한 NP 짓입니까...=ㅁ=

    문득 생각이 났는데, 이 문제를 푸는 데 시간표 만드는 프로그램의 알고리즘이 괜찮을 것 같습니다.

    답글삭제
  14. @Un-i-que - 2009/10/17 16:10
    그럼 샘플 코드 좀... 굽신 굽신...

    답글삭제
  15. @BLUEnLIVE - 2009/10/17 16:46
    없어서 죄송합니다 :P ㅋㅋㅋㅋㅋㅋㅋ

    답글삭제
  16. @Un-i-que - 2009/10/17 16:10
    풋! 그럼 무효.

    이 문제는 NP 수준 문제인 거임.

    답글삭제
  17. @BLUEnLIVE - 2009/10/29 00:29
    헐-_-; 하지만 시간표 만드는 프로그램이 실제로 있잖습니까 ㅎㅎ 저는 그다지 찾을 생각이 없으니...(?)

    답글삭제
  18. @5분만에 풀었는뎅ㅡㅡ - 2009/11/21 18:32
    네이버 사절

    답글삭제
  19. I don't even know how I ended up here, however I thought this publish was once good. I don't know who you are but definitely you're going to a famous blogger should you aren't already.
    Cheers!
    Here is my homepage ; cigarettes online

    답글삭제
  20. Sweet blog! I found it while surfing around on Yahoo News.
    Do you have any suggestions on how to get listed in Yahoo News?
    I've been trying for a while but I never seem to get there! Many thanks
    Review my webpage piano lessons

    답글삭제
  21. Howdy exceptional website! Does running a blog similar
    to this take a large amount of work? I have very little
    knowledge of computer programming but I was hoping to start my own blog soon.
    Anyway, should you have any suggestions or techniques for new blog owners please share.

    I know this is off topic however I simply needed to ask.

    Kudos!
    Feel free to surf my page ... how to download movies

    답글삭제
  22. Pretty great post. I just stumbled upon your weblog and wished to mention that I've truly loved surfing around your blog posts. After all I will be subscribing for your feed and I'm
    hoping you write again soon!
    Also visit my blog post ... www.youtube.com

    답글삭제
  23. Superb blog! Do you have any helpful hints for
    aspiring writers? I'm hoping to start my own site soon but I'm a little lost on everything.

    Would you suggest starting with a free platform like
    Wordpress or go for a paid option? There are so many choices out there that I'm totally overwhelmed .. Any suggestions? Many thanks!
    Check out my webpage - acne and teens

    답글삭제
  24. Thanks for your personal marvelous posting!

    I really enjoyed reading it, you will be a great author.
    I will ensure that I bookmark your blog and will often come back
    from now on. I want to encourage you continue your great work, have
    a nice morning!
    Also see my website: how to get rid of bed bugs

    답글삭제
  25. Howdy very cool website!! Guy .. Beautiful .. Amazing .. I will bookmark your website and take the feeds additionally?
    I am happy to seek out numerous helpful information right
    here in the publish, we'd like develop more techniques in this regard, thanks for sharing. . . . . .
    Here is my blog : Make Money working At Home

    답글삭제
  26. You really make it seem so easy with your presentation but I find this topic to be actually something
    which I think I would never understand. It seems too complicated and very broad for me.
    I'm looking forward for your next post, I will try to get the hang of it!
    Also visit my blog post :: skin lightening pills

    답글삭제
  27. I am sure this paragraph has touched all the internet viewers, its really really
    good article on building up new blog.
    Also visit my webpage : Villa Turkista

    답글삭제
  28. I do not even understand how I finished up right here,
    however I believed this put up used to be good. I do not know
    who you might be however certainly you are going to a famous blogger in case you
    are not already. Cheers!
    Here is my blog post : Properties in Antalya

    답글삭제
  29. I'm really enjoying the design and layout of your website. It's a very easy on the eyes which makes
    it much more enjoyable for me to come here and visit more often.
    Did you hire out a designer to create your theme? Outstanding work!
    Here is my blog Wohnungen Antalya

    답글삭제
  30. I'm really enjoying the design and layout of your website. It's a very easy on the eyes which makes it much more enjoyable for me to come
    here and visit more often. Did you hire out a designer to create your theme?
    Outstanding work!
    My site :: Wohnungen Antalya

    답글삭제
  31. Genuinely no matter if someone doesn't know afterward its up to other visitors that they will help, so here it happens.
    Feel free to visit my web-site - Bolig til salgs i Bodrum

    답글삭제
  32. This paragraph will help the internet users for creating new
    weblog or even a blog from start to end.
    Also see my web page :: Villa Antalyasta

    답글삭제
  33. I know this web page offers quality dependent content and other material, is
    there any other web page which gives these information in quality?
    Here is my site ... Hus i Antalya

    답글삭제
  34. Write more, thats all I have to say. Literally, it
    seems as though you relied on the video to make
    your point. You obviously know what youre talking about, why waste your intelligence on just posting
    videos to your weblog when you could be giving us something informative to read?
    Also see my page :: real Estate Alanya

    답글삭제
  35. I love what you guys are usually up too. This type of clever work and coverage!
    Keep up the amazing works guys I've included you guys to our blogroll.
    Stop by my web page - Mahmutlar Alanya

    답글삭제
  36. Its like you read my mind! You seem to know so much
    about this, like you wrote the book in it or something.
    I think that you could do with a few pics to drive the message home a little bit, but
    other than that, this is great blog. A fantastic read. I will definitely be back.
    Also visit my blog post ; skin bleaching

    답글삭제
  37. Hello! I just would like to offer you a huge thumbs up
    for your great information you have here on this post. I am coming
    back to your website for more soon.
    My webpage ... skin lightening cream

    답글삭제
  38. you're in point of fact a good webmaster. The website loading speed is amazing. It sort of feels that you're doing
    any distinctive trick. Also, The contents
    are masterpiece. you've done a great activity in this matter!
    Check out my web-site :: laser tattoo removal

    답글삭제
  39. Thiѕ desіgn is stelleг! Υou obviouslу know hoω to κeeρ а reаdеr enteгtaіned.

    Βetween your wit and your videoѕ, I ωas аlmoѕt moveԁ
    to start mу own blоg (well, almoѕt...HаHа!

    ) Wonderful job. І гeаlly loѵeԁ whаt yοu had to sау, and morе thаn that,
    how you ρreѕеnted іt. Too cоol!


    Ѕtop by my weblog Furnished Apartments

    답글삭제
  40. Thiѕ is reаlly intеresting, You are а verу ѕkilleԁ blοgger.
    I've joined your feed and look forward to seeking more of your fantastic post. Also, I have shared your web site in my social networks!

    Also visit my web blog: green carpet cleaning phoenix

    답글삭제
  41. Andy Ilias is a co-writer for To get more fun anԁ enjoyable offiсе Christmas paгty games
    ideas, yοu сan find a grеat lіѕt.
    Purpοse: This will help with mаѕtery of basic math facts and faster rеcall οf mаth
    fаcts. From thгee to six monthѕ he will start to grasp a toy that is plaсed
    in his hand, and will begin tο reаch for toys.

    Demonstrate a simple dοmino game with plаyers takіng turns to match eіther end of thе linе.
    Yοu can get many options and ideaѕ of oгganizing the party οnline.



    My website ... free unblоcked gameѕ ()

    답글삭제
  42. Excellent beat ! I wish to apprentice even as you amend your website, how can i subscribe for a weblog web site?
    The account aided me a appropriate deal. I have been tiny
    bit acquainted of this your broadcast provided vivid transparent concept

    my web page - garage door opener repair phoenix

    답글삭제
  43. Whаt's up to every , because I am in fact keen of reading this weblog's pоst tо
    bе updatеd rеgularly. It carries nice information.


    Mу web-site ankle tattoos

    답글삭제
  44. Greate article. Keep writing such kind of info on your
    site. Im really impressed by it.
    Hi there, You've performed a great job. I will definitely digg it and in my opinion recommend to my friends. I'm confident they'll be benefited from this website.

    Have a look at my site - free seo training online

    답글삭제
  45. Oh my goodness! Amazing article ԁude! Thank you so
    much, However I аm encountering troubles with your
    RSS. I don't know the reason why I am unable to join it. Is there anybody having identical RSS problems? Anybody who knows the solution can you kindly respond? Thanks!!

    Here is my webpage - angel tattoo designs ()

    답글삭제