За последние 24 часа нас посетили 22353 программиста и 1022 робота. Сейчас ищут 673 программиста ...

Цепи Маркова и текст

Тема в разделе "Решения, алгоритмы", создана пользователем an_v, 11 мар 2010.

  1. an_v

    an_v Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    3
    Симпатии:
    0
    :)
    везде в инете говорят, что подобной лабуды в сети хоть лопатой греби. Но! может быть я плохо ищу, может быть даже яша с гуглом научились определять не только тексты, сделанные подобным образом (опять же как говорят в сети :)) но и статьи о подобных способом и теперь подобной инфы не найти - ее уже выкинули из индекса.
    К делу. Поискал я по сети алгоритмы подобной генерации текста, нашел всего три разновидности и все они работают только с цепями маркова первого порядка, а это для текста не есть хорошо.
    НО! есть один вариантик, вроде как по описанию (да и по коду) он работает с более высокими порядками.
    поскольку зааттачить файл нельза, выкладываю то, что нашел в сети:
    PHP:
    1. <?
    2.     /*
    3.      * class for Markov's chains realization
    4.      * (c) Andrey, [email=somemilk.org@gmail.com]somemilk.org@gmail.com[/email], 2006
    5.      *
    6.      * Typical usage:
    7.      * $m = new Markov(2); // 2 - markov chain length, depends on source
    8.      *                     // file size, 2 for small files, 3-4 for large ones
    9.      * $m->initFromFile("somefile.txt") or die("shit happens.");
    10.      * $bullshit = $m->generate(2000); // generates bullshit 2000 chars long.
    11.      * $m->initFromString(file_get_contents("somefile.txt")) or die("shit happens.");
    12.      * $bullshit = $m->generate(100, MARKOV_OPT_WORDS); // generates bullshit 100 words long.
    13.      */
    14.  
    15.     define("MARKOV_OPT_CHARACTERS", 1); // option: character limit for generate()
    16.     define("MARKOV_OPT_WORDS",      2); // option: word limit for generate()
    17.     define("MARKOV_DEFAULT_K",      3); // default Markov chain length
    18.     define("MARKOV_TIME_LIMIT",     120); // time limit for initFromFile()
    19.  
    20.     define("MARKOV_MAX_RECURSION_LEVEL",     20);
    21.  
    22.     class Markov
    23.     {
    24.         var $k = MARKOV_DEFAULT_K;
    25.         var $k_sets = array();
    26.         var $split_method = MARKOV_OPT_WORDS;
    27.  
    28.         function Markov($k, $split_method = MARKOV_OPT_WORDS)
    29.         {
    30.             $this->k = $k;
    31.             $this->split_method = $split_method;
    32.         }
    33.  
    34.         /*
    35.          * inits class' Markov k-sets with a text from a text file.
    36.          *
    37.          * returns true on success, false on failure
    38.          */
    39.         function initFromFile($filename)
    40.         {
    41.             set_time_limit(MARKOV_TIME_LIMIT);
    42.  
    43.             if(!is_readable($filename)) return false;
    44.  
    45.             $fc = file_get_contents($filename);
    46.             $this->initFromString($fc);
    47.  
    48.             return true;
    49.         }
    50.  
    51.         /*
    52.          * inits class' Markov k-sets with a text from a string.
    53.          *
    54.          * returns true on success, false on failure
    55.          */
    56.         function initFromString($str)
    57.         {
    58.             if(strlen($str) k) return false;
    59.             $this->k_sets = array();
    60.             $set = array();
    61.  
    62.             if($this->split_method == MARKOV_OPT_WORDS)
    63.             {
    64.                 $words = preg_split('/\s+/', trim($str));
    65.                 if(count($words) k) return false;
    66.                 foreach($words as $w)
    67.                 {
    68.                     $this->_addToSets($set, $w);
    69.                 }
    70.             }
    71.             else
    72.             {
    73.                 for($i=0; $i_addToSets($set, substr($str, $i, 1));
    74.                 }
    75.             }
    76.  
    77.             return true;
    78.         }
    79.  
    80.         function _addToSets(&$set, $w)
    81.         {
    82.             $set[] = $w;
    83.             if(count($set) == $this->k)
    84.             {
    85.                 $key = "";
    86.                 for($i=0; $ik - 1; $i++)
    87.                 {
    88.                     $key .= "[\$set[$i]]";
    89.                 }
    90.                 eval("\$this->k_sets{$key}[] = \$set[$i];");
    91.                 array_shift($set);
    92.             }
    93.         }
    94.  
    95.         /*
    96.          * you must re-init the class after calling setK()
    97.          */
    98.         function setK($k) { $this->k = $k; $this->k_sets = array(); }
    99.  
    100.         /*
    101.          * generates random word $length characters long
    102.          * (available only if split_method is MARKOV_OPT_CHARACTERS
    103.          */
    104.         function getWord($length)
    105.         {
    106.             if($this->split_method != MARKOV_OPT_CHARACTERS) return false;
    107.             $res = "";
    108.             $set = array();
    109.             while(strlen($res) k)
    110.                 {
    111.                     $word = array_shift($set);
    112.                     if(preg_match('/[\s\.,:\?!;"]/', $word))
    113.                     {
    114.                         $res = "";
    115.                         continue;
    116.                     }
    117.  
    118.                     $res .= $word;
    119.                 }
    120.  
    121.                 if(strlen($res) == $length) break;
    122.  
    123.                 if(count($set)) $element =& $this->k_sets[$set[0]];
    124.                 else $element = null;
    125.                 foreach($set as $i => $word)
    126.                 {
    127.                     if(isset($element[$word])) $element =& $element[$word];
    128.                 }
    129.                 if(is_array($element))
    130.                 {
    131.                     $word = $this->random_key($element);
    132.                     if(is_array($element[$word])) $set[] = $word;
    133.                     else $set[] = $this->random_value($element);
    134.                 }
    135.                 else $set[] = $this->random_key($this->k_sets);
    136.  
    137.             }
    138.             return $res;
    139.         }
    140.  
    141.         /*
    142.          * generates Markov's string, max $how_much long,
    143.          * in words (if $how==MARKOV_OPT_WORDS)
    144.          * or in characters (if $how==MARKOV_OPT_CHARACTERS, default)
    145.          */
    146.         function generate($how_much, $how=MARKOV_OPT_CHARACTERS, $sentences=false, $recursion_level=0)
    147.         {
    148.             $res = "";
    149.             $n_words = 0;
    150.             $set = array();
    151.             $sentence_started = false;
    152.             while(($how == MARKOV_OPT_CHARACTERS && (strlen($res) < $how_much)) ||
    153.                   ($how == MARKOV_OPT_WORDS && ($n_words k)
    154.                 {
    155.                     $res .= ($word = array_shift($set));
    156.                     if($this->split_method == MARKOV_OPT_WORDS)
    157.                     {
    158.                         $res .= " ";
    159.                         $n_words++;
    160.                     }
    161.                     elseif(preg_match('/[\s\.,:\?!;"]/', $word))
    162.                     {
    163.                         $n_words++;
    164.                     }
    165.                     if($sentences && !$sentence_started && preg_match('/\.$/', $word))
    166.                     {
    167.                         $sentence_started = true;
    168.                         $res = "";
    169.                         $n_words = 0;
    170.                     }
    171.                 }
    172.  
    173.                 if(count($set)) $element =& $this->k_sets[$set[0]];
    174.                 else $element = null;
    175.                 foreach($set as $i => $word)
    176.                 {
    177.                     if(isset($element[$word])) $element =& $element[$word];
    178.                 }
    179.                 if(is_array($element))
    180.                 {
    181.                     $word = $this->random_key($element);
    182.                     if(is_array($element[$word])) $set[] = $word;
    183.                     else $set[] = $this->random_value($element);
    184.                 }
    185.                 else $set[] = $this->random_key($this->k_sets);
    186.  
    187.             }
    188.             $res = rtrim($res);
    189.             if($sentences)
    190.             {
    191.                 $res = preg_replace('/\.[^\.]+$/', '.', $res);
    192.                 if(!preg_match('/\.$/', $res) && ($recursion_level generate($how_much, $how, $sentences, $recursion_level+1));
    193.             }
    194.             return $res;
    195.         }
    196.  
    197.         /*
    198.          * helper function, returns random array key
    199.          */
    200.         function random_key(&$array)
    201.         {
    202.             $rand = mt_rand(0, count($array) - 1);
    203.             $i = 0;
    204.             foreach($array as $key => $value) if($i++ == $rand) return $key;
    205.         }
    206.         /*
    207.          * helper function, returns random array value
    208.          */
    209.         function random_value(&$array)
    210.         {
    211.             $rand = mt_rand(0, count($array) - 1);
    212.             $i = 0;
    213.             foreach($array as $key => $value) if($i++ == $rand) return $value;
    214.         }
    215.     }
    216. ?>
    В коде куча ошибок: скобки, какие-то "к" по тексту. короче после чистки он, наверное, должен быть таким:
    PHP:
    1. <?
    2.     /*
    3.      * class for Markov's chains realization
    4.      * (c) Andrey, [email=somemilk.org@gmail.com]somemilk.org@gmail.com[/email], 2006
    5.      *
    6.      * Typical usage:
    7.      * $m = new Markov(2); // 2 - markov chain length, depends on source
    8.      *                     // file size, 2 for small files, 3-4 for large ones
    9.      * $m->initFromFile("somefile.txt") or die("shit happens.");
    10.      * $bullshit = $m->generate(2000); // generates bullshit 2000 chars long.
    11.      * $m->initFromString(file_get_contents("somefile.txt")) or die("shit happens.");
    12.      * $bullshit = $m->generate(100, MARKOV_OPT_WORDS); // generates bullshit 100 words long.
    13.      */
    14.  
    15.     define("MARKOV_OPT_CHARACTERS", 1); // option: character limit for generate()
    16.     define("MARKOV_OPT_WORDS",      2); // option: word limit for generate()
    17.     define("MARKOV_DEFAULT_K",      3); // default Markov chain length
    18.     define("MARKOV_TIME_LIMIT",     1200); // time limit for initFromFile()
    19.  
    20.     define("MARKOV_MAX_RECURSION_LEVEL",     20);
    21.  
    22.     class Markov
    23.     {
    24.         var $k = MARKOV_DEFAULT_K;
    25.         var $setk = array();
    26.         var $split_method = MARKOV_OPT_WORDS;
    27.  
    28.         function Markov($k, $split_method = MARKOV_OPT_WORDS)
    29.         {
    30.             $this->k = $k;
    31.             $this->split_method = $split_method;
    32.         }
    33.  
    34.         /*
    35.          * inits class' Markov k-sets with a text from a text file.
    36.          *
    37.          * returns true on success, false on failure
    38.          */
    39.         function initFromFile($filename)
    40.         {
    41.             set_time_limit(MARKOV_TIME_LIMIT);
    42.  
    43.             if(!is_readable($filename)) return false;
    44.  
    45.             $fc = file_get_contents($filename);
    46.             $this->initFromString($fc);
    47.             echo "InitFromFile true";
    48.             return true;
    49.         }
    50.  
    51.         /*
    52.          * inits class' Markov k-sets with a text from a string.
    53.          *
    54.          * returns true on success, false on failure
    55.          */
    56.         function initFromString($str)
    57.         {
    58.             if(strlen($str)) return false;
    59.             $this->setk = array();
    60.             $set = array();
    61.  
    62.             if($this->split_method == MARKOV_OPT_WORDS)
    63.             {
    64.                 $words = preg_split('/\s+/', trim($str));
    65.                 if(count($words)) return false;
    66.                 foreach($words as $w)
    67.                 {
    68.                     $this->_addToSets($set, $w);
    69.                 }
    70.             }
    71.             else
    72.             {
    73.                 for($i=0; $i_addToSets<$set; substr($str, $i, 1));
    74.             }
    75.            
    76.  
    77.             return true;
    78.         }
    79.  
    80.         function _addToSets(&$set, $w)
    81.         {
    82.             $set[] = $w;
    83.             if(count($set) == $this->k)
    84.             {
    85.                 $key = "";
    86.                 for($i=0; $ik - 1; $i++)
    87.                 {
    88.                     $key .= "[\$set[$i]]";
    89.                 }
    90.                 eval("\$this->setk{$key}[] = \$set[$i];");
    91.                 array_shift($set);
    92.             }
    93.         }
    94.  
    95.         /*
    96.          * you must re-init the class after calling setK()
    97.          */
    98.         function setK($k) { $this->k = $k; $this->setk = array(); }
    99.  
    100.         /*
    101.          * generates random word $length characters long
    102.          * (available only if split_method is MARKOV_OPT_CHARACTERS
    103.          */
    104.         function getWord($length)
    105.         {
    106.             if($this->split_method != MARKOV_OPT_CHARACTERS) return false;
    107.             $res = "";
    108.             $set = array();
    109.             while(strlen($res))
    110.                 {
    111.                     $word = array_shift($set);
    112.                     if(preg_match('/[\s\.,:\?!;"]/', $word))
    113.                     {
    114.                         $res = "";
    115.                         continue;
    116.                     }
    117.  
    118.                     $res .= $word;
    119.                 }
    120.  
    121.                 if(strlen($res) == $length) break;
    122.  
    123.                 if(count($set)) $element =& $this->setk[$set[0]];
    124.                 else $element = null;
    125.                 foreach($set as $i => $word)
    126.                 {
    127.                     if(isset($element[$word])) $element =& $element[$word];
    128.                 }
    129.                 if(is_array($element))
    130.                 {
    131.                     $word = $this->random_key($element);
    132.                     if(is_array($element[$word])) $set[] = $word;
    133.                     else $set[] = $this->random_value($element);
    134.                 }
    135.                 else $set[] = $this->random_key($this->setk);
    136.  
    137.            
    138.             return $res;
    139.         }
    140.  
    141.         /*
    142.          * generates Markov's string, max $how_much long,
    143.          * in words (if $how==MARKOV_OPT_WORDS)
    144.          * or in characters (if $how==MARKOV_OPT_CHARACTERS, default)
    145.          */
    146.         function generate($how_much, $how=MARKOV_OPT_CHARACTERS, $sentences=false, $recursion_level=0)
    147.         {
    148.             $res = "";
    149.             $n_words = 0;
    150.             $set = array();
    151.             $sentence_started = false;
    152.             while(($how == MARKOV_OPT_CHARACTERS && (strlen($res) < $how_much)) || ($how == MARKOV_OPT_WORDS && ($n_words)))
    153.                 {
    154.                     $res .= ($word = array_shift($set));
    155.                     if($this->split_method == MARKOV_OPT_WORDS)
    156.                     {
    157.                         $res .= " ";
    158.                         $n_words++;
    159.                     }
    160.                     elseif(preg_match('/[\s\.,:\?!;"]/', $word))
    161.                     {
    162.                         $n_words++;
    163.                     }
    164.                     if($sentences && !$sentence_started && preg_match('/\.$/', $word))
    165.                     {
    166.                         $sentence_started = true;
    167.                         $res = "";
    168.                         $n_words = 0;
    169.                     }
    170.                 }
    171.                 echo "while ok";
    172.                 if(count($set)) $element =& $this->setk[$set[0]];
    173.                 else $element = null;
    174.                 echo "if ok";
    175.                 foreach($set as $i => $word)
    176.                 {
    177.                     if(isset($element[$word])) $element =& $element[$word];
    178.                 }
    179.                 echo "foreach ok";
    180.                 if(is_array($element))
    181.                 {
    182.                     $word = $this->random_key($element);
    183.                     if(is_array($element[$word])) $set[] = $word;
    184.                     else $set[] = $this->random_value($element);
    185.                 }
    186.                 else $set[] = $this->random_key($this->setk);
    187.                 $t=implode(" ", $set);
    188.                 echo "<br>".$t;
    189.            
    190.             $res = rtrim($res);
    191.             if($sentences)
    192.             {
    193.                 $res = preg_replace('/\.[^\.]+$/', '.', $res);
    194.                 if(!preg_match('/\.$/', $res) && ($recursion_level)) generate($how_much, $how, $sentences, $recursion_level+1);
    195.             }
    196.             return $res;
    197.         }
    198.  
    199.         /*
    200.          * helper function, returns random array key
    201.          */
    202.         function random_key(&$array)
    203.         {
    204.             $rand = mt_rand(0, count($array) - 1);
    205.             $i = 0;
    206.             foreach($array as $key => $value) if($i++ == $rand) return $key;
    207.         }
    208.         /*
    209.          * helper function, returns random array value
    210.          */
    211.         function random_value(&$array)
    212.         {
    213.             $rand = mt_rand(0, count($array) - 1);
    214.             $i = 0;
    215.             foreach($array as $key => $value) if($i++ == $rand) return $value;
    216.         }
    217.     }
    218.    
    219.    
    220.    
    221. ?>
    вызываю его так, как написано:
    PHP:
    1.   $m = new Markov(4)
    2.     $bullshit = $m->generate(100, MARKOV_OPT_WORDS);
    3.     echo $bullshit;
    а в ответ тишина....
    если $res посмотреть после генерации, то окажется, что массив-то пуст!

    А теперь ВОПРОС.
    может у кого-нибудь есть готовые подобные решения (цепи Маркова n-го порядка) или давайте разберемся с кодом, и он вдруг окажется рабочим?
    очень надеюсь на вашу помощь.
    пс: не для ГС и не для генерации дорвеев мне это надо. просто у этой фичи есть и много других способов применения.
     
  2. an_v

    an_v Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    3
    Симпатии:
    0
    Короче поковырял я тут этот код еще.
    в PHP я не очень сильно волоку, но что я заметил:

    в функции InitFromFile в начале стоит код
    PHP:
    1. if(strlen($str)) return false;
    а аргумент говорят надо вставлять массив
    PHP:
    1. file_get_contents("somefile.txt");
    эта функция всегда возвратит 0

    или я чего-то не понял?
    Ребят, разве гуру программинга здесь нет? другие темы довольно живо обсуждаются, а здесь никто помочь не может.
    Скажите просто: будет этот код работать или нет?
     
  3. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    вернет содержимое файла полностью
    Если файл есть.

    Код может и будет работать, но заниматься отладкой я точно не буду
     
  4. an_v

    an_v Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    3
    Симпатии:
    0
    да я не про эту функцию. я про strlen,
    PHP:
    1. if(strlen($str)) return false;
    здесь же всегда будет false(ну если эта строка $str есть)? то есть у меня есть подозрение что этот код нифига работать не будет.
    может есть готовые решения, которыми не жалко поделиться?
    Ншел еще пару вариантов в буржуйском нете, могу выложить если надо. но там по-моему цепей маркова совсем нет. там просто тупо рандомное перетасовывание предложений. Мне надо именно алгоритм Маркова, чтобы можно было менять длину цепей
     
  5. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Если длина строки 0, то вернет false.