This is my weekly Kata post. Read the first one to learn what it is all about.
Last week: Word Wrap
In PHP/Behat I learned about scenario outlines, which remove a lot of repetition in feature files. Full result:
Feature: Word Wrap In order to display text on tiny screens I want to wrap lines of a long text Scenario Outline: Wrap text When I wrap <text> at <col> columns Then I should retrieve the wrapped string <wrapped> Examples: | text | col | wrapped | | | 1 | | | word | 2 | wo\nrd | | word | 3 | wor\nd | | word | 4 | word | | word | 5 | word | | word word | 4 | word\nword | | word word | 5 | word\nword | | word word | 7 | word\nword | | word word | 8 | word\nword | | word word | 9 | word word | | abcdefg hij klmno p qurstuvwx yz | 4 | abcd\nefg\nhij\nklmn\no p\nqurs\ntuvw\nx yz | <?php use Behat\Behat\Context\Context; class WordwrapContext implements Context { private $result; /** * @When /^I wrap (.*) at (.*) columns$/ */ public function iWrapAtColumns($text, $col) { $this->result = wrap($text, $col); } /** * @Then /^I should retrieve the wrapped string (.*)$/ */ public function iShouldRetrieveTheWrappedString($wrapped) { $this->assertEquals(str_replace('\n', "\n", $wrapped), $this->result); } private function assertEquals($expected, $actual) { if (gettype($expected) != gettype($actual)) { throw new LogicException("Expected type " . gettype($expected). ", got " . gettype($actual)); } if ($expected !== $actual) { throw new LogicException("Expected " . var_export($expected, true) . ", got " . var_export($actual, true)); } } } function wrap(string $text, int $columnSize): string { if (strlen($text) <= $columnSize) { return $text; } $splitPosition = min(strrpos($text, ' '), $columnSize) ?: $columnSize; return trim(substr($text, 0, $splitPosition)) . "\n" . wrap(trim(substr($text, $splitPosition)), $columnSize); }
In Ruby, the Kata made me learn about string indexing, it took me a while to get it to work as intended and it probably is not very idiomatic. Full result:
gem 'minitest', '~> 5.4' require 'minitest/autorun' class WordWrapTest < Minitest::Test def assert_wrap expected, text, columns assert_equal expected, wrap(text, columns) end def test_single_short_word assert_wrap "word", "word", 4 end def test_single_long_word assert_wrap "long\nword", "longword", 4 end def test_single_very_long_word assert_wrap "very\nlong\nword", "verylongword", 4 end def test_space_before_wrap assert_wrap "two\nword\ns", "two words", 4 end def test_space_after_wrap assert_wrap "long\nword", "long word", 4 end def test_space_somewhere_else assert_wrap "abc\nde\nfghi\njk", "abc de fghi jk", 4 end end def wrap text, columns if text.length <= columns then return text end break_at = text[0..columns-1].index(" ") || columns if text[break_at] == " " then line_start = break_at + 1 else line_start = break_at end text[0..break_at-1] + "\n" + wrap(text[line_start..-1], columns) end
Fifth Kata: Karate Chop
The ordinary name of “Karate Chop” is “Binary Search”. A binary search algorithm finds the position of a value in a sorted array of values. The kata is described at http://codekata.com/kata/kata02-karate-chop/ where you are encouraged to find five unique approaches.
My personal goals this week
- Come up with five unique approaches.
- Use different languages as they fit. I don’t want to settle for techniques yet.