Kumite (ko͞omiˌtā) is the practice of taking techniques learned from Kata and applying them through the act of freestyle sparring.
You can create a new kumite by providing some initial code and optionally some test cases. From there other warriors can spar with you, by enhancing, refactoring and translating your code. There is no limit to how many warriors you can spar with.
A great use for kumite is to begin an idea for a kata as one. You can collaborate with other code warriors until you have it right, then you can convert it to a kata.
public class Average { public static int averageFinder(int[] arr) { int total = 0; for(int num: arr){ total += num; } return total / arr.length; } }
- public class Average {
- public static int averageFinder(int[] arr) {
- int total = 0;
- for(int num: arr){
- total += num;
- }
int result = total / arr.length;return result;- return total / arr.length;
- }
- }
Faster than previsous versions by avoiding sorting and insertion of factor lists. Style fix (not is not a function)
def divisors(n): fact_lo = [] fact_hi = [] for i in range(1, int(n**0.5) + 1): if not n % i: v = n // i if v != i: fact_hi.append(v) fact_lo.append(i) fact_lo.extend(reversed(fact_hi)) return fact_lo
- def divisors(n):
fact = []- fact_lo = []
- fact_hi = []
- for i in range(1, int(n**0.5) + 1):
if not(n % i):- if not n % i:
- v = n // i
- if v != i:
fact.insert(len(fact)//2,v)fact.insert(len(fact)//2,i)return fact- fact_hi.append(v)
- fact_lo.append(i)
- fact_lo.extend(reversed(fact_hi))
- return fact_lo
Outline
This is a proposal for CodeWars test framework for Python to improve it in many ways (and be more consistent with other languages' frameworks).
Unlike my previous Kumite, this one is designed to completely replace cw-2.py
in the runner repo.
Changes / Improvements
Individual Testing / Logging Functions
- Make testing functions non-blocking
- Change the expression inside
assert_not_equals
so that it can prevent operator injection hacks - Provide a way to log and test Unicode strings without Unicode-related error
- Provide a utility for timeout
- Provide
pass
,fail
andassert_approx_equals
Describe / It
- Build the decorator version of
describe
andit
, so the text fixture may look like this (and the decorator itself runs the code, so it doesn't need a separate runner function):
@describe('describe-text')
def describe1():
@it('it-text', before=f1, after=f2)
def it1():
# some test function
@it('it-text')
def it2():
# some test function
- Properly close
describe
andit
blocks in the test output - Print the running times of
describe
andit
blocks - Provide
before
andafter
fordescribe
andit
Changelog
v1.1
- Replace the timeout utility with decorator version.
v1.2
- Make the whole code (including fixture examples) compatible with Python 2 using
six
.
from __future__ import print_function import re, six range = six.moves.range class AssertException(Exception): pass '''Fix the dreaded Unicode Error Trap''' def uni_print(*args, **kwargs): from sys import stdout sep = kwargs.get('sep', ' ') end = kwargs.get('end', '\n') file = kwargs.get('file', stdout) def _replace(c): if ord(c) >= 128: return u'&#{};'.format(ord(c)) return c def _escape(s): escaped = ''.join(_replace(c) for c in six.text_type(s)) escaped = re.sub(r'\\u([\da-f]{4})', lambda m: '&#{};'.format(int(m.group(1), 16)), escaped) escaped = re.sub(r'\\U([\da-f]{8})', lambda m: '&#{};'.format(int(m.group(1), 16)), escaped) return escaped six.print_(*map(_escape, args), sep=_escape(sep), end=_escape(end), file=file) def format_message(message): def _replace(c): if ord(c) >= 65536: return r'\U' + hex(ord(c))[2:].zfill(8) if ord(c) >= 128: return r'\u' + hex(ord(c))[2:].zfill(4) return c def _escape(s): return ''.join(_replace(c) for c in s) return _escape(message.replace("\n", "<:LF:>")) def display(type, message, label="", mode=""): print("\n<{0}:{1}:{2}>{3}".format(type.upper(), mode.upper(), label, format_message(message))) def expect(passed=None, message=None, allow_raise=False): if passed: display('PASSED', 'Test Passed') else: message = message or "Value is not what was expected" display('FAILED', message) if allow_raise: raise AssertException(message) def assert_equals(actual, expected, message=None, allow_raise=False): equals_msg = "{0} should equal {1}".format(repr(actual), repr(expected)) if message is None: message = equals_msg else: message += ": " + equals_msg expect(actual == expected, message, allow_raise) def assert_not_equals(actual, expected, message=None, allow_raise=False): equals_msg = "{0} should not equal {1}".format(repr(actual), repr(expected)) if message is None: message = equals_msg else: message += ": " + equals_msg expect(not (actual == expected), message, allow_raise) def expect_error(message, function): passed = False try: function() except: passed = True expect(passed, message) def pass_(): expect(True) def fail(message): expect(False, message) def assert_approx_equals(actual, expected, margin=1e-9, message=None, allow_raise=False): equals_msg = "{0} should be close to {1} with absolute or relative margin of {2}".format( repr(actual), repr(expected), repr(margin)) if message is None: message = equals_msg else: message += ": " + equals_msg div = max(abs(actual), abs(expected), 1) expect(abs((actual - expected) / div) < margin, message, allow_raise) ''' Usage: @describe('describe text') def describe1(): @it('it text') def it1(): # some test cases... ''' def _timed_block_factory(opening_text): from timeit import default_timer as timer from traceback import format_exception from sys import exc_info def _timed_block_decorator(s, before=None, after=None): display(opening_text, s) def wrapper(func): if callable(before): before() time = timer() try: func() except: fail('Unexpected exception raised') tb_str = ''.join(format_exception(*exc_info())) display('ERROR', tb_str) display('COMPLETEDIN', '{:.2f}'.format((timer() - time) * 1000)) if callable(after): after() return wrapper return _timed_block_decorator describe = _timed_block_factory('DESCRIBE') it = _timed_block_factory('IT') ''' Timeout utility Usage: @timeout(sec) def some_tests(): any code block... Note: Timeout value can be a float. ''' def timeout(sec): def wrapper(func): from multiprocessing import Process process = Process(target=func) process.start() process.join(sec) if process.is_alive(): fail('Exceeded time limit of {:.3f} seconds'.format(sec)) process.terminate() process.join() return wrapper '''Old-style Fixture''' describe('Old-style Describe') it('Old-style It') assert_equals(0, 0) assert_equals(0, 1) print('<COMPLETEDIN::>') it('Old-style It 2') assert_equals('a', 'a') assert_equals('a', 'b') print('<COMPLETEDIN::>') print('<COMPLETEDIN::>') '''Sample Fixture #1''' @describe('Sample Fixture #1') def sample_describe_1(): @it('Sample Testcase #1-1') def sample_it_1(): assert_equals(0, 0) assert_equals(0, 1) assert_not_equals(0, 2) pass_() fail('This should fail') @it('Sample Testcase #1-2') def sample_it_2(): expect_error('ZeroDivisionError', lambda: 0 / 0) assert_equals(0, 0 / 0) assert_equals(1, 1, 'This is not run due to exception') @it('Sample Testcase #1-3') def sample_it_3(): assert_equals('abc', 'abc') # source code doesn't support utf-8 chars, but you can at least log and test unicode assert_equals(u'\uac00 \ub098 \ub2e4', u'\uac00 \ub098 \ub2e4') uni_print(1, 'a', u'\uac00 \ub098 \ub2e4', [2, 'b', u'\uac00']) assert_equals(u'\uac00 \ub098 \ub2e4', 'a b c') '''Sample Fixture #2: Featuring Before and After''' @describe('Sample Fixture #2') def sample_describe_2(): a = {0} def before(): a.add(len(a)) @it('Sample Testcase #2-1', before=before, after=before) def sample_it_1(): assert_equals(a, {0, 1}) @it('Sample Testcase #2-2') def sample_it_2(): assert_equals(a, {0, 1, 2}) '''Sample Fixture #3: Featuring Timeout''' @describe('Sample Fixture #3') def sample_describe_3(): @it('Sample Testcase #3-1') def sample_it_1(): @timeout(0.01) def count(): for _ in range(100): pass pass_() @it('Sample Testcase #3-2') def sample_it_2(): @timeout(0.01) def count(): for _ in range(10**10): pass pass_() '''Sample Fixture #4: Featuring assert_approx_equals''' @describe('Sample Fixture #4') def sample_describe_4(): @it('Sample Testcase #4-1') def sample_it_1(): assert_approx_equals(1, 1 + 1e-10, 1e-9) assert_approx_equals(1, 1 + 1e-7, 1e-9) assert_approx_equals(-1, -1 - 1e-10, 1e-9) assert_approx_equals(-1, -1 - 1e-7, 1e-9) @it('Sample Testcase #4-2') def sample_it_2(): assert_approx_equals(0, 1e-10, 1e-9) assert_approx_equals(0, 1e-7, 1e-9) assert_approx_equals(0, -1e-10, 1e-9) assert_approx_equals(0, -1e-7, 1e-9)
#from __future__ import print_function- from __future__ import print_function
- import re, six
- range = six.moves.range
- class AssertException(Exception):
- pass
- '''Fix the dreaded Unicode Error Trap'''
_print = printdef print(*args, sep=' ', end=''):from io import StringIOdef _escape(s): return s.encode('ascii', 'xmlcharrefreplace').decode('ascii')sio = StringIO()_print(*args, sep=sep, end=end, file=sio)_print(_escape(sio.getvalue()))sio.close()- def uni_print(*args, **kwargs):
- from sys import stdout
- sep = kwargs.get('sep', ' ')
- end = kwargs.get('end', '
- ')
- file = kwargs.get('file', stdout)
- def _replace(c):
- if ord(c) >= 128: return u'&#{};'.format(ord(c))
- return c
- def _escape(s):
- escaped = ''.join(_replace(c) for c in six.text_type(s))
- escaped = re.sub(r'\\u([\da-f]{4})', lambda m: '&#{};'.format(int(m.group(1), 16)), escaped)
- escaped = re.sub(r'\\U([\da-f]{8})', lambda m: '&#{};'.format(int(m.group(1), 16)), escaped)
- return escaped
- six.print_(*map(_escape, args), sep=_escape(sep), end=_escape(end), file=file)
- def format_message(message):
return message.replace("", "<:LF:>")- def _replace(c):
- if ord(c) >= 65536: return r'\U' + hex(ord(c))[2:].zfill(8)
- if ord(c) >= 128: return r'\u' + hex(ord(c))[2:].zfill(4)
- return c
- def _escape(s): return ''.join(_replace(c) for c in s)
- return _escape(message.replace("
- ", "<:LF:>"))
- def display(type, message, label="", mode=""):
- print("\n<{0}:{1}:{2}>{3}".format(type.upper(), mode.upper(), label, format_message(message)))
- def expect(passed=None, message=None, allow_raise=False):
if passed: print("\n<PASSED::>Test Passed")- if passed:
- display('PASSED', 'Test Passed')
- else:
- message = message or "Value is not what was expected"
print("\n<FAILED::>{0}".format(message))if allow_raise: raise AssertException(message)- display('FAILED', message)
- if allow_raise:
- raise AssertException(message)
'''Fix the blocking asserts to non-blocking'''- def assert_equals(actual, expected, message=None, allow_raise=False):
- equals_msg = "{0} should equal {1}".format(repr(actual), repr(expected))
if message is None: message = equals_msgelse: message += ": " + equals_msg- if message is None:
- message = equals_msg
- else:
- message += ": " + equals_msg
- expect(actual == expected, message, allow_raise)
'''Fix the blocking asserts to non-blockingAlso change the expected formula from `actual != expected` to `not (actual == expected)`so that using this assertion can prevent the `==` / `!=` injection hack'''- def assert_not_equals(actual, expected, message=None, allow_raise=False):
- equals_msg = "{0} should not equal {1}".format(repr(actual), repr(expected))
if message is None: message = equals_msgelse: message += ": " + equals_msg- if message is None:
- message = equals_msg
- else:
- message += ": " + equals_msg
- expect(not (actual == expected), message, allow_raise)
- def expect_error(message, function):
- passed = False
try: function()except: passed = True- try:
- function()
- except:
- passed = True
- expect(passed, message)
'''Additional test functions: pass, fail, and assert_approx_equals'''- def pass_(): expect(True)
- def fail(message): expect(False, message)
- def assert_approx_equals(actual, expected, margin=1e-9, message=None, allow_raise=False):
- equals_msg = "{0} should be close to {1} with absolute or relative margin of {2}".format(
- repr(actual), repr(expected), repr(margin))
- if message is None: message = equals_msg
- else: message += ": " + equals_msg
- div = max(abs(actual), abs(expected), 1)
- expect(abs((actual - expected) / div) < margin, message, allow_raise)
def display(type, message, label="", mode=""):print("\n<{0}:{1}:{2}>{3}".format(type.upper(), mode.upper(), label, format_message(message)))- '''
Modern-Style Describe & It- Usage:
- @describe('describe text')
- def describe1():
- @it('it text')
- def it1():
- # some test cases...
- '''
- def _timed_block_factory(opening_text):
- from timeit import default_timer as timer
- from traceback import format_exception
- from sys import exc_info
- def _timed_block_decorator(s, before=None, after=None):
print('<{}::>{}'.format(opening_text, s))- display(opening_text, s)
- def wrapper(func):
- if callable(before): before()
- time = timer()
- try: func()
- except:
- fail('Unexpected exception raised')
tb_str = ''.join(format_exception(*exc_info())).replace('\n', '<:LF:>')print('<ERROR::>' + tb_str)print('<COMPLETEDIN::>{}'.format(round((timer() - time) * 1000, 2)))- tb_str = ''.join(format_exception(*exc_info()))
- display('ERROR', tb_str)
- display('COMPLETEDIN', '{:.2f}'.format((timer() - time) * 1000))
- if callable(after): after()
- return wrapper
- return _timed_block_decorator
- describe = _timed_block_factory('DESCRIBE')
- it = _timed_block_factory('IT')
- '''
- Timeout utility
- Usage:
with run_with_timeout(func, tuple_of_args, timeout_in_seconds) as run:Test.assert_equals(run.get(), expected_value)- @timeout(sec)
- def some_tests():
- any code block...
- Note: Timeout value can be a float.
- '''
class run_with_timeout(object):def __init__(self, func, inputs, sec):from multiprocessing import Process, Queuedef timeout_wrapper(func, inputs, q):q.put(func(*inputs))self.sec = secself.q = Queue()self.p = Process(target=timeout_wrapper, args=(func, inputs, self.q))self.result = Nonedef __enter__(self):self.p.start()return selfdef get(self):if self.result is None: self.result = self.q.get(timeout=self.sec)return self.resultdef __exit__(self, typ, val, traceback):self.q.close()self.p.terminate()self.p.join()if traceback: fail('Exceeded time limit of {:.3f} seconds'.format(self.sec))return True- def timeout(sec):
- def wrapper(func):
- from multiprocessing import Process
- process = Process(target=func)
- process.start()
- process.join(sec)
- if process.is_alive():
- fail('Exceeded time limit of {:.3f} seconds'.format(sec))
- process.terminate()
- process.join()
- return wrapper
- '''Old-style Fixture'''
- describe('Old-style Describe')
- it('Old-style It')
- assert_equals(0, 0)
- assert_equals(0, 1)
- print('<COMPLETEDIN::>')
- it('Old-style It 2')
- assert_equals('a', 'a')
- assert_equals('a', 'b')
- print('<COMPLETEDIN::>')
- print('<COMPLETEDIN::>')
- '''Sample Fixture #1'''
- @describe('Sample Fixture #1')
- def sample_describe_1():
- @it('Sample Testcase #1-1')
- def sample_it_1():
- assert_equals(0, 0)
- assert_equals(0, 1)
- assert_not_equals(0, 2)
- pass_()
- fail('This should fail')
- @it('Sample Testcase #1-2')
- def sample_it_2():
- expect_error('ZeroDivisionError', lambda: 0 / 0)
- assert_equals(0, 0 / 0)
- assert_equals(1, 1, 'This is not run due to exception')
- @it('Sample Testcase #1-3')
- def sample_it_3():
- assert_equals('abc', 'abc')
- # source code doesn't support utf-8 chars, but you can at least log and test unicode
assert_equals('\uac00 \ub098 \ub2e4', '\uac00 \ub098 \ub2e4')print('\uac00 \ub098 \ub2e4')assert_equals('\uac00 \ub098 \ub2e4', 'a b c')- assert_equals(u'\uac00 \ub098 \ub2e4', u'\uac00 \ub098 \ub2e4')
- uni_print(1, 'a', u'\uac00 \ub098 \ub2e4', [2, 'b', u'\uac00'])
- assert_equals(u'\uac00 \ub098 \ub2e4', 'a b c')
- '''Sample Fixture #2: Featuring Before and After'''
- @describe('Sample Fixture #2')
- def sample_describe_2():
- a = {0}
- def before():
- a.add(len(a))
- @it('Sample Testcase #2-1', before=before, after=before)
- def sample_it_1():
- assert_equals(a, {0, 1})
- @it('Sample Testcase #2-2')
- def sample_it_2():
- assert_equals(a, {0, 1, 2})
- '''Sample Fixture #3: Featuring Timeout'''
- @describe('Sample Fixture #3')
- def sample_describe_3():
def wait_count(n):for _ in range(n): passreturn n- @it('Sample Testcase #3-1')
- def sample_it_1():
with run_with_timeout(wait_count, (100,), 0.01) as run:assert_equals(run.get(), 100)- @timeout(0.01)
- def count():
- for _ in range(100): pass
- pass_()
- @it('Sample Testcase #3-2')
- def sample_it_2():
with run_with_timeout(wait_count, (10 ** 10,), 0.01) as run:assert_equals(run.get(), 10 ** 10)- @timeout(0.01)
- def count():
- for _ in range(10**10): pass
- pass_()
- '''Sample Fixture #4: Featuring assert_approx_equals'''
- @describe('Sample Fixture #4')
- def sample_describe_4():
- @it('Sample Testcase #4-1')
- def sample_it_1():
- assert_approx_equals(1, 1 + 1e-10, 1e-9)
- assert_approx_equals(1, 1 + 1e-7, 1e-9)
- assert_approx_equals(-1, -1 - 1e-10, 1e-9)
- assert_approx_equals(-1, -1 - 1e-7, 1e-9)
- @it('Sample Testcase #4-2')
- def sample_it_2():
- assert_approx_equals(0, 1e-10, 1e-9)
- assert_approx_equals(0, 1e-7, 1e-9)
- assert_approx_equals(0, -1e-10, 1e-9)
- assert_approx_equals(0, -1e-7, 1e-9)
A simple FizzBuzz implementation, to try out Kumites.
Take a positive integer as input, and output:
"Fizz" if the number is divisible by three
"Buzz" if the number is divisible by five
"FizzBuzz" if the number is divisible by three and five
otherwise, just the number (as a string)
using System; namespace Solution { class FizzBuzz { public static string convert(int input) { var output = (input % 3 == 0 ? "Fizz" : "") + (input % 5 == 0 ? "Buzz" : ""); return output == "" ? input.ToString() : output; } } }
- using System;
- namespace Solution {
- class FizzBuzz {
- public static string convert(int input)
- {
var output = "";- var output = (input % 3 == 0 ? "Fizz" : "") + (input % 5 == 0 ? "Buzz" : "");
output += (input % 3 == 0) ? "Fizz" : "";output += (input % 5 == 0) ? "Buzz" : "";output += (string.IsNullOrEmpty(output)) ? input.ToString() : "";return output;- return output == "" ? input.ToString() : output;
- }
- }
- }
namespace Solution { using NUnit.Framework; using System; [TestFixture] public class SolutionTest { [Test] public void NotDivisibleByThreeOrFive() { Assert.That(FizzBuzz.convert(1), Is.EqualTo("1")); Assert.That(FizzBuzz.convert(7), Is.EqualTo("7")); } [Test] public void DivisibleByThree() { Assert.That(FizzBuzz.convert(3), Is.EqualTo("Fizz")); Assert.That(FizzBuzz.convert(12), Is.EqualTo("Fizz")); } [Test] public void DivisibleByFive() { Assert.That(FizzBuzz.convert(5), Is.EqualTo("Buzz")); Assert.That(FizzBuzz.convert(95), Is.EqualTo("Buzz")); } [Test] public void DivisibleByThreeAndFive() { Assert.That(FizzBuzz.convert(15), Is.EqualTo("FizzBuzz")); Assert.That(FizzBuzz.convert(90), Is.EqualTo("FizzBuzz")); } } }
- namespace Solution {
- using NUnit.Framework;
- using System;
// TODO: Replace examples and use TDD development by writing your own tests- [TestFixture]
- public class SolutionTest
- {
- [Test]
- public void NotDivisibleByThreeOrFive()
- {
- Assert.That(FizzBuzz.convert(1), Is.EqualTo("1"));
- Assert.That(FizzBuzz.convert(7), Is.EqualTo("7"));
- }
- [Test]
- public void DivisibleByThree()
- {
- Assert.That(FizzBuzz.convert(3), Is.EqualTo("Fizz"));
- Assert.That(FizzBuzz.convert(12), Is.EqualTo("Fizz"));
- }
- [Test]
- public void DivisibleByFive()
- {
- Assert.That(FizzBuzz.convert(5), Is.EqualTo("Buzz"));
- Assert.That(FizzBuzz.convert(95), Is.EqualTo("Buzz"));
- }
- [Test]
- public void DivisibleByThreeAndFive()
- {
- Assert.That(FizzBuzz.convert(15), Is.EqualTo("FizzBuzz"));
- Assert.That(FizzBuzz.convert(90), Is.EqualTo("FizzBuzz"));
- }
- }
- }
This shows a piece of test code in Python that is improved over the default cw-2
(and consistent with other languages' test frameworks) in the following aspects:
Initial release (v1.0)
- Utilize the
with
-block to support proper indentation ofdescribe
andit
blocks in the code - Properly close
describe
andit
blocks in the test output - Print the running times of
describe
andit
blocks - Make testing functions non-blocking
v1.1
- Provide a way to log Unicode strings for users (does not work for test framework)
v1.2
- Provide
before
andafter
fordescribe
andit
- Provide a utility for timeout
- Version 1: Function version
- Version 2: Context manager version (looks cleaner)
Run the tests and see how the test output looks like.
''' Fix for the dreaded Unicode Trap (works in py3+) This does not fix the test outputs, so some revision in cw-2 is needed ''' from io import StringIO import sys _print = print def _escape(s): return s.encode('ascii', 'xmlcharrefreplace').decode('ascii') def print(*args, sep=' ', end='\n', file=sys.stdout): sio = StringIO() _print(*args, sep=sep, end=end, file=sio) _print(_escape(sio.getvalue()), file=file) sio.close() print('\uac00 \ub098 \ub2e4 <\'">\\') ''' Defining `describe` and `it` properly Allows `with`-structure, properly outputs <COMPLETEDIN::> with timing information, and also supports optional `before` and `after`. ''' from timeit import default_timer as timer from traceback import format_exception def timed_block_wrapper(func): class _wrapper(object): def __init__(self, name, before=None, after=None): self.name = name self.func = func self.timer = None self.before = before self.after = after def __enter__(self): self.func(self.name) if callable(self.before): self.before() self.timer = timer() def __exit__(self, typ, val, traceback): if traceback: test.expect(False, 'Unexpected exception raised') tb_str = ''.join(format_exception(typ, val, traceback)).replace('\n', '<:LF:>') print('<ERROR::>{}'.format(tb_str)) print('<COMPLETEDIN::>{}'.format(round((timer() - self.timer) * 1000, 2))) if callable(self.after): self.after() return True return _wrapper Test.describe = timed_block_wrapper(Test.describe) Test.it = timed_block_wrapper(Test.it) ''' Non-blocking test failures There are only four testing functions provided by CW (expect, assert_equals, assert_not_equals, expect_error), two of which are blocking functions (i.e. stops execution on failure). If you write customized test functions, you don't need this fix as long as you use Test.expect and provide helpful messages. ''' AssertException = __import__('cw-2').AssertException def test_wrapper(func): def wrapped(*args, **kwargs): try: func(*args, **kwargs) except AssertException: pass return wrapped Test.assert_equals = test_wrapper(Test.assert_equals) Test.assert_not_equals = test_wrapper(Test.assert_not_equals) ''' Timeout utility ''' from multiprocessing import Process, Queue from queue import Empty def run_with_timeout(func, inputs, sec): def timeout_wrapper(func, inputs, q): q.put(func(*inputs)) q = Queue() p = Process(target=timeout_wrapper, args=(func, inputs, q)) p.start() ret = None try: ret = q.get(timeout=sec) q.close() p.join() return ret except Empty: q.close() p.terminate() p.join() Test.expect(False, 'Exceeded time limit of {:.3f} seconds'.format(sec)) ''' Sample test fixture ''' with Test.describe('Unicode'): with Test.it('Simple'): Test.assert_equals('\uac00 \ub098 \ub2e4', 'a b c') with Test.describe('Fibonacci'): with Test.it('Simple'): Test.assert_equals(fibonacci(1), 2) Test.assert_not_equals(fibonacci(1), 2) Test.assert_not_equals(fibonacci(1), 1) Test.assert_equals(fibonacci(5), 8) Test.assert_equals(fibonacci(10), 89) with Test.it('Higher'): Test.assert_equals(fibonacci(15), 987) Test.assert_equals(fibonacci(20), 10946) Test.assert_equals(fibonacci(25), 121393) Test.assert_equals(fibonacci(30), 1346269) with Test.it('Extreme'): Test.assert_equals(fibonacci(32), 3524578) Test.expect_error('Some message', lambda: fibonacci(36)) Test.expect_error('Some other message', lambda: fibonacci(1)) Test.assert_equals(fibonacci(36), 0) with Test.describe('Before/After'): a = 0 def before(): global a a += 1 with Test.it('Simple', before=before): Test.assert_equals(a, 1) with Test.it('Another', before=before): Test.assert_equals(a, 2) with Test.describe('Timeout'): with Test.it('Simple'): actual = run_with_timeout(fibonacci, (20,), 0.01) Test.assert_equals(actual, 10946) actual = run_with_timeout(fibonacci, (25,), 0.01) Test.assert_equals(actual, 121393) class run_with_timeout2(object): def __init__(self, func, inputs, sec): def timeout_wrapper(func, inputs, q): q.put(func(*inputs)) self.sec = sec self.q = Queue() self.p = Process(target=timeout_wrapper, args=(func, inputs, self.q)) self.result = None def __enter__(self): self.p.start() return self def get(self): if self.result is None: self.result = self.q.get(timeout=self.sec) return self.result def __exit__(self, typ, val, traceback): self.q.close() self.p.terminate() self.p.join() if traceback: Test.expect(False, 'Exceeded time limit of {:.3f} seconds'.format(self.sec)) return True with Test.describe('Timeout2'): with Test.it('Simple'): with run_with_timeout2(fibonacci, (20,), 0.01) as run: Test.assert_equals(run.get(), 10946) with run_with_timeout2(fibonacci, (25,), 0.01) as run: Test.assert_equals(run.get(), 121393)
- '''
- Fix for the dreaded Unicode Trap (works in py3+)
- This does not fix the test outputs, so some revision in cw-2 is needed
- '''
- from io import StringIO
- import sys
- _print = print
- def _escape(s): return s.encode('ascii', 'xmlcharrefreplace').decode('ascii')
- def print(*args, sep=' ', end='\n', file=sys.stdout):
- sio = StringIO()
- _print(*args, sep=sep, end=end, file=sio)
- _print(_escape(sio.getvalue()), file=file)
- sio.close()
- print('\uac00 \ub098 \ub2e4 <\'">\\')
- '''
- Defining `describe` and `it` properly
- Allows `with`-structure, properly outputs <COMPLETEDIN::> with timing information,
- and also supports optional `before` and `after`.
- '''
- from timeit import default_timer as timer
- from traceback import format_exception
- def timed_block_wrapper(func):
- class _wrapper(object):
def __init__(self, name):- def __init__(self, name, before=None, after=None):
- self.name = name
- self.func = func
- self.timer = None
- self.before = before
- self.after = after
- def __enter__(self):
- self.func(self.name)
- if callable(self.before): self.before()
- self.timer = timer()
- def __exit__(self, typ, val, traceback):
- if traceback:
- test.expect(False, 'Unexpected exception raised')
- tb_str = ''.join(format_exception(typ, val, traceback)).replace('\n', '<:LF:>')
- print('<ERROR::>{}'.format(tb_str))
- print('<COMPLETEDIN::>{}'.format(round((timer() - self.timer) * 1000, 2)))
- if callable(self.after): self.after()
- return True
- return _wrapper
- Test.describe = timed_block_wrapper(Test.describe)
- Test.it = timed_block_wrapper(Test.it)
- '''
- Non-blocking test failures
- There are only four testing functions provided by CW (expect, assert_equals, assert_not_equals, expect_error),
- two of which are blocking functions (i.e. stops execution on failure).
- If you write customized test functions, you don't need this fix as long as you use Test.expect and provide helpful messages.
- '''
- AssertException = __import__('cw-2').AssertException
- def test_wrapper(func):
- def wrapped(*args, **kwargs):
- try: func(*args, **kwargs)
- except AssertException: pass
- return wrapped
- Test.assert_equals = test_wrapper(Test.assert_equals)
- Test.assert_not_equals = test_wrapper(Test.assert_not_equals)
- '''
- Timeout utility
- '''
- from multiprocessing import Process, Queue
- from queue import Empty
- def run_with_timeout(func, inputs, sec):
- def timeout_wrapper(func, inputs, q):
- q.put(func(*inputs))
- q = Queue()
- p = Process(target=timeout_wrapper, args=(func, inputs, q))
- p.start()
- ret = None
- try:
- ret = q.get(timeout=sec)
- q.close()
- p.join()
- return ret
- except Empty:
- q.close()
- p.terminate()
- p.join()
- Test.expect(False, 'Exceeded time limit of {:.3f} seconds'.format(sec))
- '''
- Sample test fixture
- '''
- with Test.describe('Unicode'):
- with Test.it('Simple'):
- Test.assert_equals('\uac00 \ub098 \ub2e4', 'a b c')
- with Test.describe('Fibonacci'):
- with Test.it('Simple'):
- Test.assert_equals(fibonacci(1), 2)
- Test.assert_not_equals(fibonacci(1), 2)
- Test.assert_not_equals(fibonacci(1), 1)
- Test.assert_equals(fibonacci(5), 8)
- Test.assert_equals(fibonacci(10), 89)
- with Test.it('Higher'):
- Test.assert_equals(fibonacci(15), 987)
- Test.assert_equals(fibonacci(20), 10946)
- Test.assert_equals(fibonacci(25), 121393)
- Test.assert_equals(fibonacci(30), 1346269)
- with Test.it('Extreme'):
- Test.assert_equals(fibonacci(32), 3524578)
- Test.expect_error('Some message', lambda: fibonacci(36))
- Test.expect_error('Some other message', lambda: fibonacci(1))
Test.assert_equals(fibonacci(36), 0)- Test.assert_equals(fibonacci(36), 0)
- with Test.describe('Before/After'):
- a = 0
- def before():
- global a
- a += 1
- with Test.it('Simple', before=before):
- Test.assert_equals(a, 1)
- with Test.it('Another', before=before):
- Test.assert_equals(a, 2)
- with Test.describe('Timeout'):
- with Test.it('Simple'):
- actual = run_with_timeout(fibonacci, (20,), 0.01)
- Test.assert_equals(actual, 10946)
- actual = run_with_timeout(fibonacci, (25,), 0.01)
- Test.assert_equals(actual, 121393)
- class run_with_timeout2(object):
- def __init__(self, func, inputs, sec):
- def timeout_wrapper(func, inputs, q):
- q.put(func(*inputs))
- self.sec = sec
- self.q = Queue()
- self.p = Process(target=timeout_wrapper, args=(func, inputs, self.q))
- self.result = None
- def __enter__(self):
- self.p.start()
- return self
- def get(self):
- if self.result is None: self.result = self.q.get(timeout=self.sec)
- return self.result
- def __exit__(self, typ, val, traceback):
- self.q.close()
- self.p.terminate()
- self.p.join()
- if traceback: Test.expect(False, 'Exceeded time limit of {:.3f} seconds'.format(self.sec))
- return True
- with Test.describe('Timeout2'):
- with Test.it('Simple'):
- with run_with_timeout2(fibonacci, (20,), 0.01) as run:
- Test.assert_equals(run.get(), 10946)
- with run_with_timeout2(fibonacci, (25,), 0.01) as run:
- Test.assert_equals(run.get(), 121393)
-[------->+<]>-.-[->+++++<]>++.+++++++..+++.[--->+<]>-----.+++[->++<]>+.-[------>+<]>.+.[--->+<]>----.---------.----.+++++++.
>++++++[<++++++++++++>-]<.>>++++++++++[<++++++++++>-]<+.+++++++..+++.>>++++[<++++++++>-]<.<<-.>--------------.+.++++++++++++++++.---------.----.+++++++.- -[------->+<]>-.-[->+++++<]>++.+++++++..+++.[--->+<]>-----.+++[->++<]>+.-[------>+<]>.+.[--->+<]>----.---------.----.+++++++.
inline float multiply(float number1, float number2 ) { float answer = 0; while( number2 > 0 ) { answer += number1; number2--; } return answer; } float squared(float number) { if( number < 0 ) number = -number; int decimal_positions = 0; while( number - int(number) > 0.1 ) { number = multiply(number, 10); decimal_positions++; } float factor = number; if( decimal_positions > 0 ) { number = multiply(number,number); switch (decimal_positions){ case 1: factor = 0.01; break; case 2: factor = 0.001; break; case 3: factor = 0.0001; break; case 4: factor = 0.00001; }} return multiply(factor,number); }
inline int multiply(int x, int y, int counter)- inline float multiply(float number1, float number2 )
- {
if (y <= 0)return 0;if (y == 1)return x;if (y & 0x1)return x + multiply(x, y - 1, 0);if (counter + counter <= y)return multiply(x + x, y >> 1, counter + counter);elsereturn x + multiply(x, y - counter, 0);- float answer = 0;
- while( number2 > 0 )
- {
- answer += number1;
- number2--;
- }
- return answer;
- }
int squared(int number)- float squared(float number)
- {
return multiply(number, number, 0);- if( number < 0 ) number = -number;
- int decimal_positions = 0;
- while( number - int(number) > 0.1 )
- {
- number = multiply(number, 10);
- decimal_positions++;
- }
- float factor = number;
- if( decimal_positions > 0 ) {
- number = multiply(number,number);
- switch (decimal_positions){
- case 1: factor = 0.01; break;
- case 2: factor = 0.001; break;
- case 3: factor = 0.0001; break;
- case 4: factor = 0.00001;
- }}
- return multiply(factor,number);
- }
Describe(squared_tests) { It(squared0_is0) { Assert::That(squared(0), Equals(0)); } It(squaredNegative0Dot5_is0Dot25) { Assert::That(squared(-0.5), EqualsWithDelta(0.25, 0.00001)); } It(squared1_is1) { Assert::That(squared(1), Equals(1)); } It(squared2_is4) { Assert::That(squared(2), Equals(4)); } It(squared3_is9) { Assert::That(squared(3), Equals(9)); } It(squared4_is16) { Assert::That(squared(4), Equals(16)); } It(squared10_is100) { Assert::That(squared(10), Equals(100)); } It(squared15_is225) { Assert::That(squared(15), Equals(225)); } It(squared21_is441) { Assert::That(squared(21), Equals(441)); } It(squared101_is10201) { Assert::That(squared(101), Equals(10201)); } };
- Describe(squared_tests)
- {
- It(squared0_is0)
- {
- Assert::That(squared(0), Equals(0));
- }
- It(squaredNegative0Dot5_is0Dot25)
- {
- Assert::That(squared(-0.5), EqualsWithDelta(0.25, 0.00001));
- }
- It(squared1_is1)
- {
- Assert::That(squared(1), Equals(1));
- }
- It(squared2_is4)
- {
- Assert::That(squared(2), Equals(4));
- }
- It(squared3_is9)
- {
- Assert::That(squared(3), Equals(9));
- }
- It(squared4_is16)
- {
- Assert::That(squared(4), Equals(16));
- }
- It(squared10_is100)
- {
- Assert::That(squared(10), Equals(100));
- }
- It(squared15_is225)
- {
- Assert::That(squared(15), Equals(225));
- }
- It(squared21_is441)
- {
- Assert::That(squared(21), Equals(441));
- }
- It(squared101_is10201)
- {
- Assert::That(squared(101), Equals(10201));
- }
- };
It is possible to exit before the end is reached, but in this example I added complexity to the model via the sorting.
import java.util.Arrays; class MaxOccurence { public static int findMax(int[] nums) { Arrays.sort(nums); int countNumberMax = -1; int numberMax = -1; int currentCount = 0; int currentNumber = nums.length>0?nums[0]:-1; for(int i = 0; i < nums.length; i++) { if(currentNumber == nums[i]) { currentCount++; if(countNumberMax < currentCount) { countNumberMax = currentCount; numberMax = currentNumber; } } else { currentCount = 1; currentNumber = nums[i]; } if(countNumberMax > nums.length/2 || countNumberMax > currentCount + nums.length - i) { break; } } return numberMax; } }
import java.util.Map;import java.util.HashMap;- import java.util.Arrays;
- class MaxOccurence {
- public static int findMax(int[] nums) {
HashMap<Integer,Integer> map = new HashMap<>();int lastBigVal = -1;int lastBigValIndx = -1;for(int i=0;i<nums.length;i++){map.putIfAbsent(nums[i],0);if(map.containsKey(nums[i])) {map.put(nums[i], map.get(nums[i]) + 1);if(lastBigVal < map.get(nums[i])) {lastBigVal = map.get(nums[i]);lastBigValIndx = nums[i];}}}return lastBigValIndx;- Arrays.sort(nums);
- int countNumberMax = -1;
- int numberMax = -1;
- int currentCount = 0;
- int currentNumber = nums.length>0?nums[0]:-1;
- for(int i = 0; i < nums.length; i++)
- {
- if(currentNumber == nums[i])
- {
- currentCount++;
- if(countNumberMax < currentCount)
- {
- countNumberMax = currentCount;
- numberMax = currentNumber;
- }
- }
- else
- {
- currentCount = 1;
- currentNumber = nums[i];
- }
- if(countNumberMax > nums.length/2 || countNumberMax > currentCount + nums.length - i)
- {
- break;
- }
- }
- return numberMax;
- }
- }