誰が嘘をついている

9723 ワード

lltongネットユーザーのブログCを拾い直して、一日少しずつ_7で小さな問題を見て、面白いと思いました.このテーマはこうです.
ある人が森で道に迷ったので、時間を見ようとしたが、時計を持っていないことに気づいた.ちょうど彼は前に2人の女の子が遊んでいるのを見て、彼は聞いてみることにした.さらに不幸なことに、この二人の女の子は欠点があって、姉は午前中に本当のことを言って、午後はうそを言って、妹は姉と正反対です.しかし、彼はやはり近づいて彼女たちに「あなたたちは誰が姉ですか?」と聞いた.太った人は「私は」と言った.痩せた人も「私は」と言った.彼はまた「今はいつですか」と聞いた.太った人は「午前中」と言った.「いいえ」と、痩せて「午後のはずです」と言った.これで彼はぼんやりしたが,いったい彼らの言うことは本当なのか.
この小さな問題が私の興味を引き起こしたのは、この問題は小さいが、書きにくいようだという直感からだ.
時には簡単に解決できる小さな問題が、コードを書くのは容易ではありません.問題が簡単すぎると、アルゴリズムが見つからないかもしれません.例えば、123が3桁であることはほとんどの人が知っていますが、初心者にとって、123が何桁であるかを求めるコードを書くのは難しいかもしれません.この問題はあまりにも簡単なので、かえって絶えず10で割る方法でこの問題を解決するとは思わなかった. 
そのため、小さな問題のコードを書くことは、意味がある場合があります.これは私たちが自分の盲点を発見し、自分の考えをはっきりさせるのに役立つからです.
次はこの問題を解いてみましょう.
この問題の1つの特徴は、姉、妹、デブ、痩せ子、本当のこと、うそ、午前、午後、そしてこれらの手がかりが複雑に絡み合っていることだ.これが,この問題が直接答えを推測できるほど小さいが,コードで解決しにくい理由の一つである.複数の要因は,微縮化して結合すればするほど解きほぐしにくくなる.通常、細い糸を解くのは太い糸を解くよりずっと難しい.理屈は同じだ.
プログラミングはまず問題を数値化し,姉や妹などを0,1という数値で表すか,コードレベルでのマッピングを行う.しかし、このような数値は私たちの思考から遠いことを示しているので、私たちはすべてを数値として考えることに慣れていません.だから、人間の思考習慣に合うために、コードの可読性のために、多くの言語はマクロ名で定数の代わりに人間の思考軌道に戻る手段を提供しています.
もう一つの一般的な手段は列挙(enum)である.列挙は、より「機械」的な思考ではなく、より自然に考えることができます.そこで、問題をどのように解決するかを考える前に、私はまずこのような声明を書きました.
問題には午前と午後があるので、
typedef enum 

      {

            ,

            ,

      }

  ;


質問に姉と妹がいたので、
typedef enum 

      {

            ,

            ,

      }

  ;

姉妹二人の答えには二つの部分があるので、
typedef struct 

      {

                  ;

                  ;

      }

  ;


答えは本当かもしれないし、嘘かもしれないので、
typedef enum 

      {

         false ,

         true ,

      }

bool;

ここで私は俗に従って、英語の単語を識別子として使いました.しかし、私はC 99が提供するboolタイプ(_Bool)を使用していません.Boolというタイプはループ文を書くのに適していない.
これにより、次のように女の子を完全に説明することができます.
typedef struct

      {

               ; 

               ;

         bool         ;

      }

  ;

女の子は全部で2人いるので、2つの変数を定義します.
          = { {    ,     } } , 

           = { {    , !   } } ;


また、その時点の時間も所定の数であるため、記録時間の変数を定義する必要があります.
         ;


今から問題の解を考えることができます.
この問題は複数の方向から着手することができる.1つの簡単な切り込み点は、どの女の子も本当のことを言うこととうそをつくことの2つの可能性しかないので、この2つを挙げるのは簡単かもしれません.
   for (   .        = false ;   .        <= true ;   .        ++ )

   {

   }

太った女の子の言うことが本当かどうかによって、姉なのか妹なのか、その時の時間を簡単に求めることができます.
           (    * ) ;

   for (   .        = false ;   .        <= true ;   .        ++ )

   {

         =         ( &    ); 



   }



           (    *   )

{

   if (   ->         == true )

   {

        ->    =   ->   .       ;

      return   ->   .       ;

   }

   else

   {

        ->    = !   ->   .       ;

      return !   ->   .       ;

   }

}

このようにして得られた結果は矛盾しているかもしれない.例えば、太った女の子がうそをついたとしたら、今は午後で、妹です.しかし、妹が午後に言ったのは本当のことで、ロスが提出した有名な理髪師のパラドックスのようにパラドックスになった.
理髪師のパラドックスはバートランド・ロスが1901年に提出したもので、村の理髪師が村のすべての自分の理髪しない人のために理髪するのを手伝ったと主張している.問題は彼が自分に散髪したかどうかだ.もし自分で散髪するならば、それでは彼自身の言うことに反して、もし彼が自分で散髪しないならば、同様に彼自身の言い方と矛盾します.このパラドックスは数学史上の3回目の危機を招き、その後の数学者は何年も忙しく働いて、数学の基礎の中でこのような矛盾を避けた.
私たちのこの問題でもパラドックスを避けるべきだ.そうしないと、でたらめな結果を招く可能性がある.したがって,さらに解く前に,このような状況を排除する必要がある.
bool     (    ,    * ) ;





      if (     (    , &    ) == true )

      {

         //    

      }





bool     (       ,    *   )

{

   switch (    )

   {

      case   :

               switch (   ->         )

               {

                  case true  : 

                              return   ->    ==    ;

                  case false : 

                              return   ->    ==    ; 

               }

      case   :

               switch (   ->         )

               {

                  case true  : 

                              return   ->    ==    ;

                  case false : 

                              return   ->    ==    ; 

               }

   }

}

矛盾を排除すれば、痩せた女の子の様々な可能性を探すことができます.
一人は姉で、もう一人は妹なので、
  .   = !  .   ;

午前中でも午後でも、一人が本当のことを言うと、もう一人がうそをつくに違いない.
  .        = !   .        ;

痩せた女の子の解の中で矛盾する可能性を排除すれば、直接結果を出力することができます.
         if (     (    , &    ) == true )

         {

            printf( "     %s 
" , . ?" ":" " ); printf( " %s
" , . ?" ":" " ); }

これで、コードは完了します.
           (    * ) ;

bool     (    ,    * ) ;



int main( void )

{



          = { {    ,     } } , 

            = { {    , !   } } ;

         ;

   

   for (   .        = false ;   .        <= true ;   .        ++ )

   {

         =         ( &    ); 

      if (     (    , &    ) == true )

      {

           .   = !  .   ;

           .        = !   .        ;

         if (     (    , &    ) == true )

         {

            printf( "     %s 
" , . ?" ":" " ); printf( " %s
" , . ?" ":" " ); } } } system("PAUSE"); return 0; } bool ( , * ) { switch ( ) { case : switch ( -> ) { case true : return -> == ; case false : return -> == ; } case : switch ( -> ) { case true : return -> == ; case false : return -> == ; } } } ( * ) { if ( -> == true ) { -> = -> . ; return -> . ; } else { -> = ! -> . ; return ! -> . ; } }

これはCコードではないと思っている人もいるかもしれませんが、実際にはCコードです.C 99以降、C言語ではこのようなコンパイラを見たことがありませんが、漢字を識別子として使用することができます.マイクロソフトのVSはC 99を支持しないと主張しているが、漢字を識別子として使用することを許可する点ではC 99を支持するのが一番だ.
残念ながらVSは手元にないので、漢字の識別子をラテン文字に変えましょう.
/*

             ,       ,          。

                ,           。

                ,

       ,      ,          。

           :“      ?”   :“  。”    :“  。”

   :       ?   :“  。”“  ”,   :“     。”

      ,           ?

*/



#include <stdio.h>

#include <stdlib.h>



typedef enum 

      {

         SW , /*    ,*/ 

         XW , /*    ,*/

      }

SJ ; /*    ;*/



typedef enum 

      {

         JJ , /*    ,*/ 

         MM , /*    ,*/

      }

JM ; /*    ;*/



typedef struct 

      {

         SJ SWHSXW ; //          ;

         JM JJHSMM ; //          ;

      }

HD ; //   ;



typedef enum 

      {

         false ,

         true ,

      }

bool;



typedef struct

      {

         HD DA ; //      ; 

         JM SF ; //      ; 

         bool SDHSZSJ ; // bool        ;

      }

NH ; //  ; 



SJ QSJBQRSF( NH * ) ; //           (   * ) ;

bool MYMD( SJ , NH * ) ; //bool     (    ,    * );



int main( void )

{



   NH PZ  = { { JJ,    SW } } , //       = { {    ,     } } ,

      SZ  = { { JJ , ! SW } } ; //         = { {    , !   } } ;

   SJ XZ ;                      //      ;

   

   for ( PZ.SDHSZSJ = false ; //for (   .        = false ;

         PZ.SDHSZSJ <= true ; //        .        <= true ;

         PZ.SDHSZSJ ++ )      //        .        ++ )

   {

      XZ = QSJBQRSF( & PZ ); //   =         ( &    ); 

      if ( MYMD( XZ , & PZ ) == true )// if (     (    , &    ) == true )

      {

         SZ.SF = !PZ.SF ;             //   .   = !  .   ;

         SZ.SDHSZSJ = ! PZ.SDHSZSJ ;  //   .        = !   .        ;

         if ( MYMD( XZ , & SZ ) == true )// if (     (    , &    ) == true )

         {

            printf( "     %s 
" , PZ.SDHSZSJ?" ":" " );// . printf( " %s
" , SZ.SDHSZSJ?" ":" " );// . } } } system("PAUSE"); return 0; } bool MYMD( SJ XZ , NH * Ta ) // bool ( , * ) { switch ( XZ /* */ ) { case SW: /* */ switch ( Ta -> SDHSZSJ /* -> */ ) { case true : return Ta -> SF == JJ ; // -> == ; case false : return Ta -> SF == MM ; // -> == ; } case XW: /* :*/ switch ( Ta -> SDHSZSJ /* -> */ ) { case true : return Ta -> SF == MM ; // -> == ; case false : return Ta -> SF == JJ ; // -> == ; } } } SJ QSJBQRSF( NH * Ta ) // ( * ) { if ( Ta -> SDHSZSJ == true ) //( -> == true ) { Ta -> SF = Ta -> DA.JJHSMM ; // -> = -> . ; return Ta -> DA.SWHSXW ; // -> . ; } else { Ta -> SF = ! Ta -> DA.JJHSMM ;// -> = ! -> . ; return ! Ta -> DA.SWHSXW ; // ! -> . ; } }