Skip to content

Instantly share code, notes, and snippets.

@shengsheng
Last active September 14, 2015 14:24
Show Gist options
  • Select an option

  • Save shengsheng/5d1a1809ec93908104d4 to your computer and use it in GitHub Desktop.

Select an option

Save shengsheng/5d1a1809ec93908104d4 to your computer and use it in GitHub Desktop.
A million monkeys write Perl and Java.
<?php
/**
* 如果有一百万只猴子,每只给一个键盘,总有一天其中一只能敲出一份完整的可运行的 Java 代码。
*
* 剩下的敲的都是 Perl 代码。
*
* @author 胡生生BSA
* @date: 2015-9-14
*/
class Keyboard
{
/**
* Keyboard name
*
* @var string
*/
private $name = 'Cherry';
/**
* Keycap lifetime
*
* @var int
*/
private $lifetime = 9223372036854775807;
/**
* @var string
*/
private $chars = '';
/**
* Accept a char
*
* @param string $char
* @return bool
*/
public function input($char)
{
if ($this->lifetime <= 0) {
return false;
}
$this->record($char);
$this->lifetime--;
return true;
}
/**
* Record everything
*
* @param string $char
*/
private function record($char)
{
$this->chars .= $char;
}
/**
* Get result
*
* @return string
*/
public function getResult()
{
return $this->chars;
}
}
class Monkey
{
/**
* @var string
*/
private $name;
/**
* Constructor
*
* @param string $name
*/
public function __construct($name)
{
$this->name = $name;
}
/**
* I'm tying
*
* @param Keyboard $keyboard
* @return bool
*/
public function typing(Keyboard $keyboard)
{
return $keyboard->input(chr(mt_rand(0, 255)));
}
/**
* I have time and want tying
*
* @return bool
*/
public function canTyping()
{
return !($this->thinking() || $this->eating() || $this->sleeping()) &&
$this->wantTyping();
}
/**
* Thinking the monkeys' future
*
* @return bool
*/
private function thinking()
{
$tmp = mt_rand(1, 100);
return $tmp >= 0 && $tmp <= 40;
}
/**
* Banana! Banana! Banana!
*
* @return bool
*/
private function eating()
{
$tmp = mt_rand(1, 100);
return $tmp >= 40 && $tmp <= 60;
}
/**
* Dream
*
* @return bool
*/
private function sleeping()
{
$tmp = mt_rand(1, 100);
return $tmp >= 60 && $tmp <= 90;
}
/**
* I'm bored
*
* @return bool
*/
private function wantTyping()
{
$tmp = mt_rand(1, 100);
return $tmp >= 90 && $tmp <= 100;
}
}
class Epic
{
/**
* @var Monkey
*/
private $monkey;
/**
* @var Keyboard
*/
private $keyboard;
/**
* Constructor
*
* @param Monkey $monkey
* @param Keyboard $keyboard
*/
public function __construct($monkey, $keyboard)
{
$this->monkey = $monkey;
$this->keyboard = $keyboard;
}
/**
* Can you write something interesting stuff?
*
* @param string $stop_time
*/
public function write($stop_time = '2038-01-19 11:14:07')
{
$stop_time = strtotime($stop_time);
while (true) {
if (time() >= $stop_time) {
break;
}
if ($this->monkey->canTyping()) {
$result = $this->monkey->typing($this->keyboard);
if (!$result) {
break;
}
}
}
}
}
class EpicTest extends PHPUnit_Framework_TestCase
{
public function millionMonkeys()
{
return array_map(function($i) { return array($i); }, range(1, 1000000));
}
/**
* @dataProvider millionMonkeys
* @param int $times
*/
public function testOneIsJavaAndRestOfThemArePerl($times)
{
$monkey = new Monkey('monkey_' . $times);
$keyboard = new Keyboard();
$epic = new Epic($monkey, $keyboard);
$epic->write();
$expect = 'Yes, PHP is the best programming language.';
$code = $keyboard->getResult();
if (isJava($code)) {
$this->assertEquals($expect, runJava(new JavaCompile($code)));
$this->assertGreaterThan(65535, strlen($code));
} else {
$this->assertEquals($expect, runPerl($code));
}
}
}
/*
jianjuo@smartisan2015 (master)$ phpunit joke.php
PHPUnit 4.6.6 by Sebastian Bergmann and contributors.
.......................................
Time: 19320310320.71 seconds, Memory: 113.75Mb
OK (1000000 tests, 1000001 assertions)
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment