« [mt.js]mt:tabを使ってみる | Home | iPhoneから投稿。 »

July 17, 2008

googleの面接のパズルを颯爽と解いてみた。

タイトルは99%関係ないんですがね。こういうパズル大好きなんですよ。
1025 学名ナナシ :2008年07月15日 21:46
今までこれ系で一番難しかったのは、

13枚のコインがあって、1枚だけ偽者があります。
偽者は重いのか軽いのかはわかりません。
天秤を3回だけ使ってどのコインが偽者か当てなさい。

どうしても解けない...

googleの面接 : アルファルファモザイク
↓10分くらいで考えた回答
とりあえず、(1)から(13)まで番号を振る
(1)(2)(3)(4)と(5)(6)(7)(8)を天秤に乗せる

傾いたら
    残りの(9)-(13)は本物
    (1)(2)(3)(5)(6)と(9)(10)(11)(12)(13)を天秤に載せる
    傾いたら
        ここで偽者が重いか軽いかが判明
        かつ、一回目の結果を考えると、(1)(2)(3) OR (5)(6) のいずれに偽者が含まれるかも判明
        (1)(2)(3)に偽者が含まれるなら
            (1)と(2)を比較。
        (5)(6)に偽者が含まれる
            (5)と(6)を比較
    傾かなかったら
        (4)(7)と(12)(13)を比較
        傾いたら
            偽者が重いか軽いかが分かる。
            かつ、一回目の結果を考えれば、(4)と(7)のどちらが重いか分かるので、判定可能
        傾かなかったら
            (8)が偽者(重いか軽いかは分からず)
傾かなかったら
    残りの(9)-(13)に偽者が含まれる。(1)から(8)は本物
    (1)(2)(3)と(9)(10)(11)を天秤に
    傾いたら
        偽者が重いか軽いかが分かる
        (9)と(10)を天秤に
    傾かなかったら
        (12)(13)のいずれかが偽者
        (1)と(12)を天秤に
で、perlで書いてみた。
#!/usr/bin/perl
use strict;
sub which_is_heavy {
    my ($left, $right) = @_;

    #この辺は本来ならブラックボックス
    my ($left_mass, $right_mass);
    map { $left_mass += $_ } @$left;
    map { $right_mass += $_ } @$right;

    return $left_mass > $right_mass    ? 'left'
            : $left_mass < $right_mass ? 'right'
            :                            'balanced';
}
 
sub get_fake_from_three {
    #偽者が重いか軽いか分かってれば3つのコインから一発で偽者を割り出せるよ関数
    my ($fake, @coins) = @_;
    if ($coins[0] > $coins[1] ) {
        return $fake eq 'heavy' ? 0 : 1;
    }
    elsif ( $coins[0] < $coins[1] ) {
        return $fake eq 'heavy' ? 1 : 0;
    }
    else {
        return 2;
    }
}
 
sub get_fake {
    my @c = @_;
    my $first_result = which_is_heavy( [ @c[0..3] ] ,[ @c[4..7] ] );
    if ($first_result eq 'balanced' ) {
        #0-7は本物
        my $second_result = which_is_heavy( [@c[0..2]], [@c[8..10]] );
        if ($second_result eq 'balanced' ) {
            #11,12が偽者
            my $third_result = which_is_heavy( [ $c[0] ], [ $c[11] ]);
            return $third_result eq 'balanced' ? 12 : 11;
        }
        else {
            #8-10に偽者かつ重いか軽いかが判明
            my $fake = $second_result eq 'left' ? 'light' : 'heavy';
            return 8 + get_fake_from_three($fake, @c[8..10]);
        }
    }
    else {
        #8-12は本物
        my $second_result = which_is_heavy( [$c[0],$c[1],$c[2],$c[4],$c[5]],[@c[8..12]] );
        if ($second_result eq 'balanced' ) {
            my $third_result = which_is_heavy( [$c[3], $c[6]], [@c[8..9]] );
            if ( $third_result eq 'left') {
                return $first_result eq 'left' ? 3 : 6;
            }
            elsif ( $third_result eq 'right' ) {
                return $first_result eq 'left' ? 6 : 3;
            }
            else {
                return 7;
            }
        }
        else {
            my $fake = $second_result eq 'left' ? 'heavy' : 'light';
            if ( ( $fake eq 'heavy' && $first_result eq 'left' )
              || ( $fake ne 'heavy' && $first_result ne 'left' ) ) {
                return get_fake_from_three( $fake, @c[0..2] );
            }
            else {
                if ( $fake eq 'heavy' ) {
                    return $c[4] > $c[5] ? 4 : 5;
                }
                else {
                    return $c[4] > $c[5] ? 5 : 4;
                }
            }
        }
    }
}
 
print get_fake( 3,2,2,2,2,2,2,2,2,2,2,2,2 ) . " will be 0\n";
print get_fake( 2,3,2,2,2,2,2,2,2,2,2,2,2 ) . " will be 1\n";
print get_fake( 2,2,3,2,2,2,2,2,2,2,2,2,2 ) . " will be 2\n";
print get_fake( 2,2,2,3,2,2,2,2,2,2,2,2,2 ) . " will be 3\n";
print get_fake( 2,2,2,2,3,2,2,2,2,2,2,2,2 ) . " will be 4\n";
print get_fake( 2,2,2,2,2,3,2,2,2,2,2,2,2 ) . " will be 5\n";
print get_fake( 2,2,2,2,2,2,3,2,2,2,2,2,2 ) . " will be 6\n";
print get_fake( 2,2,2,2,2,2,2,3,2,2,2,2,2 ) . " will be 7\n";
print get_fake( 2,2,2,2,2,2,2,2,3,2,2,2,2 ) . " will be 8\n";
print get_fake( 2,2,2,2,2,2,2,2,2,3,2,2,2 ) . " will be 9\n";
print get_fake( 2,2,2,2,2,2,2,2,2,2,3,2,2 ) . " will be 10\n";
print get_fake( 2,2,2,2,2,2,2,2,2,2,2,3,2 ) . " will be 11\n";
print get_fake( 2,2,2,2,2,2,2,2,2,2,2,2,3 ) . " will be 12\n";
 
print get_fake( 1,2,2,2,2,2,2,2,2,2,2,2,2 ) . " will be 0\n";
print get_fake( 2,1,2,2,2,2,2,2,2,2,2,2,2 ) . " will be 1\n";
print get_fake( 2,2,1,2,2,2,2,2,2,2,2,2,2 ) . " will be 2\n";
print get_fake( 2,2,2,1,2,2,2,2,2,2,2,2,2 ) . " will be 3\n";
print get_fake( 2,2,2,2,1,2,2,2,2,2,2,2,2 ) . " will be 4\n";
print get_fake( 2,2,2,2,2,1,2,2,2,2,2,2,2 ) . " will be 5\n";
print get_fake( 2,2,2,2,2,2,1,2,2,2,2,2,2 ) . " will be 6\n";
print get_fake( 2,2,2,2,2,2,2,1,2,2,2,2,2 ) . " will be 7\n";
print get_fake( 2,2,2,2,2,2,2,2,1,2,2,2,2 ) . " will be 8\n";
print get_fake( 2,2,2,2,2,2,2,2,2,1,2,2,2 ) . " will be 9\n";
print get_fake( 2,2,2,2,2,2,2,2,2,2,1,2,2 ) . " will be 10\n";
print get_fake( 2,2,2,2,2,2,2,2,2,2,2,1,2 ) . " will be 11\n";
print get_fake( 2,2,2,2,2,2,2,2,2,2,2,2,1 ) . " will be 12\n";
 

No TrackBacks

TrackBack URL: http://aklaswad.com/cgi-bin/mt/mt-tb.cgi/254

Leave a comment

OpenID accepted here Learn more about OpenID

About this Entry

This page contains a single entry by aklaswad published on July 17, 2008 11:45 PM.

[mt.js]mt:tabを使ってみる was the previous entry in this blog.

iPhoneから投稿。 is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.