Scalaスケーラブルプログラミングから2Dレイアウトライブラリー
Scalaスケーラブルプログラミングの2DレイアウトライブラリーをPHPに変換してみた。
ただそれだけ。
テスト環境はWindowsのPHP5.4.7。
- 作者: Martin Odersky,Lex Spoon,Bill Venners,羽生田栄一,水島宏太,長尾高弘
- 出版社/メーカー: インプレスジャパン
- 発売日: 2011/09/27
- メディア: 単行本(ソフトカバー)
- 購入: 9人 クリック: 216回
- この商品を含むブログ (39件) を見る
Element.php
<?php abstract class Element { /** * @return array(string) */ abstract public function contents(); /** * @return int */ public function height() { return count($this->contents()); } /** * @return int */ public function width() { if($this->height() == 0) { return 0; } else { $contents = $this->contents(); return strlen($contents[0]); } } /** * @param int $w * @return Element */ public function widen($w) { if($w <= $this->width()) { return $this; } else { $left = self::elem(' ', ($w - $this->width()) / 2, $this->height()); $right = self::elem(' ', $w - $this->width() - $left->width(), $this->height()); return $left->beside($this)->beside($right); } } /** * @param int $h * @return Element */ public function heighten($h) { if($h <= $this->height()) { return $this; } else { $top = self::elem(' ', $this->width(), ($h - $this->height()) / 2 ); $bot = self::elem(' ', $this->width(), $h - $this->height() - $top->height() ); return $top->above($this)->above($bot); } } /** * @param Element $that * @return Element */ public function above(Element $that) { $this1 = $this->widen($that->width()); $that1 = $that->widen($this->width()); $newContents = $this1->contents(); foreach($that1->contents() as $data) { $newContents[] = $data; } return self::elem($newContents); } /** * @param Element $that * @return Element */ public function beside(Element $that) { $this1 = $this->heighten($that->height()); $that1 = $that->heighten($this->height()); $this1Contents = $this1->contents(); $that1Contents = $that1->contents(); $max = $this1->height(); $newContents = array(); for($i=0; $i<$max; $i++) { $newContents[] = $this1Contents[$i] . $that1Contents[$i]; } return self::elem($newContents); } /** * @return string */ public function __toString() { return join("\n", $this->contents()); } // ==================================================================== // STATIC // ==================================================================== /** * @param char|string|array(string) $data * @param int $arg1 * @param int $arg2 * @return Element */ public static function elem($data, $arg1 = null, $arg2 = null) { if(is_null($arg1)) { return self::elemStrings($data); } else { return self::elemUniform($data, $arg1, $arg2); } } /** * @param string|array(string) * @return Element */ private static function elemStrings($contentsOrLine) { if(is_array($contentsOrLine)) { return new ArrayElement($contentsOrLine); } else { return new LineElement($contentsOrLine); } } /** * @param char $ch * @param width $width * @param height $height * @return Element */ private static function elemUniform($chr, $width, $height) { return new UniformElement($chr, intval($width), intval($height)); } } class ArrayElement extends Element { /** * @var array */ protected $contents; /** * @param array(string) $contents */ public function __construct(array $contents) { $this->contents = $contents; } public function contents() { return $this->contents; } } class LineElement extends Element { protected $line; /** * @param string $line */ public function __construct($line) { if(!is_string($line) or !strlen($line)) { throw new Exception("Param Error"); } $this->line = $line; } public function contents() { return array($this->line); } public function width() { return strlen($this->line); } public function height() { return 1; } } class UniformElement extends Element { protected $line; protected $h; /** * @param char $ch * @param int $width * @param int $height */ public function __construct($ch, $width, $height) { if(!is_string($ch) or strlen($ch) != 1) { throw new Exception("Param Error [ch]"); } if(!is_numeric($width)) { throw new Exception("Param Error [width]"); } if(!is_numeric($height)) { throw new Exception("Param Error [height]"); } $h = intval($height); $w = intval($width); $this->line = str_repeat($ch, $w); $this->h = $h; } public function contents() { if($this->h <= 0) { return array(); } return array_fill(0, $this->h, $this->line); } }
index.php
<?php require dirname(__FILE__) . '/Element.php'; if( isset($argv[1]) and ($nEdges = intval($argv[1])) ) { $start = microtime(true); $result = spiral($nEdges, 0); $last = microtime(true); echo $result , "\n"; echo 'memory_get_peak_usage: ' , (memory_get_peak_usage(true) / 1024) , " KB\n"; echo 'process time: ' , sprintf('%01.6f', ($last - $start)) , "\n"; } function spiral($nEdges, $direction) { $space = Element::elem(' '); $corner = Element::elem('+'); if($nEdges == 1) { return Element::elem("+"); } else { $sp = spiral($nEdges - 1, ($direction + 3) % 4 ); $vertivalBar = Element::elem('|', 1, $sp->height()); $horizontalBar = Element::elem('-', $sp->width(), 1); switch($direction) { case 0: return $corner->beside($horizontalBar) ->above( $sp->beside($space) ); case 1: return $sp->above($space) ->beside( $corner->above($vertivalBar) ); case 2: return $space->beside($sp) ->above( $horizontalBar->beside($corner) ); default: return $vertivalBar->above($corner) ->beside( $space->above($sp) ); } } }
php index.php 6
とすると次のように表示される。
+----- | | +-+ | + | | | +---+ memory_get_peak_usage: 256 KB process time: 0.000386