Begin a new Kumite
Search
About
  • Filter by Language:
  • 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.

Code
Diff
  • using System;
    
    namespace Solution {
    
      class FizzBuzz {
        public static Func<int, string> convert = (input) 
                => {
                  var output = $"{input % 3 == 0 ? "Fizz" : string.Empty}{input % 5 == 0 ? "Buzz" : string.Empty}";
                  return !string.IsNullOrWhiteSpace(output) ? output : input.ToString();
                };
      }
    }
  • 11 using System;
    22
    33 namespace Solution {
    44
    55 class FizzBuzz {
    6- public static string convert(int input)
    7- {
    8- var output = (input % 3 == 0 ? "Fizz" : "") + (input % 5 == 0 ? "Buzz" : "");
    9-
    10- return output == "" ? input.ToString() : output;
    11- }
    6+ public static Func<int, string> convert = (input)
    7+ => {
    8+ var output = $"{input % 3 == 0 ? "Fizz" : string.Empty}{input % 5 == 0 ? "Buzz" : string.Empty}";
    9+ return !string.IsNullOrWhiteSpace(output) ? output : input.ToString();
    10+ };
    1212 }
    1313 }

In this kata you should find BB-tags (bulletin board tags) in given string.

BB-tags look like:

[B]Some content[/B],

where [B] - opening tag and [/B] - closing tag.

Name of tags also can be lowercase:

[url]Some content[/url]

And BB-tags can be nested into each other, for example:

[url][b][size=5][color=blue]Some content[/color][/size][/b][/url]

If there is nested BB-tags, you should return only the outer tag with all it's content (with another tags into it).

function test(str) {
  return (str.match(/\[([a-zA-Z]+)](.*)\[\/\1]/g)).join('');
}

BRAINFUCK VIZUALISER

How to use it:

Debugging commands usable in the BF code:
    '?' char in the code to choose the debugging points.
        You cnan name the check points with r'\w+' characters after the ?
    '!' char to switch on/off the full debugging (print at the execution of each segment)
Other global switches available:
     ALL:         vizualisation at each step of the code (each segment). Only when you're desperate...
     DEACTIVATE:  force the deactivation of the vizualisation whatever is found in the code or the other switches are
     CHAR_MODE:   if True, the tape will display ascii chars instead of numbers (Note: unprintable chars won't show up...)
     LIMITER:     interrupt the executions after this number of printing. The count is reseted for each test

Here is the kind of output you get, with the code joint (note: I messed up the code of a previously completed kata):

Input:  3


?START
[ 0,  1, 51]   tape
[ 0,  0,  1]   p
out = ''


?REMOVE_SOME
[ 0,  1, 13,  0]   tape
[ 0,  0,  1,  0]   p
out = ''


?ISNOTDOT
[ 0,  1, 51,  0,  1]   tape
[ 0,  0,  0,  0,  1]   p
out = ''


?GET_DECIMAL
[ 0,  1, 51,  0,  0,  0]   tape
[ 0,  0,  0,  0,  0,  1]   p
out = ''
Input:  3
3  should be  3
SUCCESS
---

Input:  1.5


?START
[ 0,  1, 49]   tape
[ 0,  0,  1]   p
out = ''


?REMOVE_SOME
[ 0,  1, 11,  0]   tape
[ 0,  0,  1,  0]   p
out = ''


?ISNOTDOT
[ 0,  1, 49,  0,  1]   tape
[ 0,  0,  0,  0,  1]   p
out = ''


?START
[ 0,  1, 49, 46,  0]   tape
[ 0,  0,  0,  1,  0]   p
out = ''


?REMOVE_SOME
[ 0,  1, 49,  8,  0]   tape
[ 0,  0,  0,  1,  0]   p
out = ''


?ISNOTDOT
[ 0,  1, 49, 46,  0,  1]   tape
[ 0,  0,  0,  0,  0,  1]   p
out = ''


?START
[ 0,  1, 49, 46, 53,  0]   tape
[ 0,  0,  0,  0,  1,  0]   p
out = ''


?REMOVE_SOME
[ 0,  1, 49, 46, 15,  0]   tape
[ 0,  0,  0,  0,  1,  0]   p
out = ''


?ISNOTDOT
[ 0,  1, 49, 46, 53,  0,  1]   tape
[ 0,  0,  0,  0,  0,  0,  1]   p
out = ''


?GET_DECIMAL
[ 0,  1, 49, 46, 53,  0,  0,  0]   tape
[ 0,  0,  0,  0,  0,  0,  0,  1]   p
out = ''
Input:  1.5
1.5  should be  2
STDERR:

Traceback:
   in <module>
AssertionError
"""
Created on Mon Oct 23 21:59:51 2017

BrainFuck tape, pointer & output vizualizer

@author: Blind4Basics - CodeWars
"""


# -----------------------------------------------------------------
#   Debugging commands usable in the BF code:
#
#       '?' char in the code to choose the debugging points.
#           You cnan name the check points with r'\w+' characters after the ?
#       '!' char to switch on/off the full debugging (print at the execution of each segment)
#
#
#   Other global switches available:
#
#        ALL:         vizualisation at each step of the code (each segment). Only when you're desperate...
#        DEACTIVATE:  force the deactivation of the vizualisation whatever is found in the code or the other switches are
#        CHAR_MODE:   if True, the tape will display ascii chars instead of numbers (Note: unprintable chars won't show up...)
#        LIMITER:     interrupt the executions after this number of printing. The count is reseted for each test
#
# -----------------------------------------------------------------


code = """                        # not working example
[
tape: _ S digits _ REF DEC S
]

>+                                 
>,
[?START                            
    >++++[<---------->-]<++        
    ?REMOVE_SOME
    [
      >++++[<++++++++++>-]<--      
      >>+<                         
    ]
    <[<]>[>]>                      
    ?ISNOTDOT
    [-<,>]<                        
]
>>,                                
?GET_DECIMAL
[                                  
    >++++[<-------->-]             
    +<<++++                        
    ?
    [->[->[>]]<<]                  
    ?MINUS4
    >[[-]<+>]                     
    ?LAST
]

<<<[<]>>[.>]
"""


#------------------------------------------------------------
#   Test cases:
#
#  'inputs' and corresponding 'expected' values
#    EOF char automatically added at the end of each input
#------------------------------------------------------------

inputs = ["3", "1.5", "101", "101.9", "101.2"]
exp =    ["3", "2",   "101", "102",   "101"]

""" GLOBAL SWITCHES """
ALL        = False
DEACTIVATE = False
CHAR_MODE  = False
LIMITER    = 50



import re

def brainFuckInterpreter(code, prog):
    
    def updateVizu(cmdSegment=''):
        
        def formatLst(lst, charMod=False):                          # Formater: align the cells of the tape and the list for the pointer
            formStr = "{: >" + str(max(map(len, map(str, data)), default=1)) + "}"
            return "[{}]".format(', '.join(formStr.format(chr(v) if charMod else v) for v in lst))
        
        if DEACTIVATE: return
        
        countDisplay[0] += 1                                        # Update the number of display already done (cf. LIMITER)
        
        vizu[-1][lastP[0]] = 0                                      # Erase the previous position of the pointer
        vizu[-1][p] = 1                                             # Place the pointer at the current position
        lastP[0] = p                                                # archive the current position of the pointer
        vizu[0] = c[0]                                              # archive the current command
        
        out = ''.join(output)
        cmd,tape,point = vizu
        print( "\n\n{}{}   tape\n{}   p\nout = '{}'".format(cmdSegment and cmdSegment+"\n",
                                                            formatLst(tape, CHAR_MODE),
                                                            formatLst(point), 
                                                            out) )
        if LIMITER >= 0 and LIMITER == countDisplay[0]: raise Exception("Too much printing: LIMITER = {}".format(LIMITER))
    
    
    def tapeLenUpdater():                                           # Make the tape length consistent with the actual position of the pointer (even if no value yet in the cells)
        if p >= len(data): 
            data.extend( [0] * (p-len(data)+1) )
            vizu[-1].extend( [0] * (len(data)-len(vizu[-1])) )
    
    
    def getNextInput():                                             # Simulate getting u'0000' when trying to get an input char after their exhaustion
        try:
            return ord(next(prog))
        except StopIteration:
            return 0
        
    
    p, lastP, i = 0, [0], 0                                         # p = pointer / lastP = previous P position (mutated) / i = segment of code index
    data = [0]                                                      # Tape initialization
    
    SWITCH, countDisplay = False, [0]                               # SWITCH: control for the "!" cmd swtich / countDisplay = control for LIMITER (as list to mutate it from a subroutine)
    output, vizu = [], ['', data, [0]]                              # vizu: [cmd, tape, pointer list]
    
    prog = iter(prog)
    code = re.findall(r'\++|<+|>+|-+|[,.[\]]|\?\w*|!', code)        # Make the executions more compact by using only segments of identical commands (=> '++++', '<<<', '[', '-', ']', check points with identifiers...)
    
    while 0 <= i < len(code):
        c = code[i]
        if False: print(c, data, p)                                 # activate manually. Only for debugging of the vizualiser itself...
        
        if   c[0] == '+': data[p] = (data[p] + len(c)) % 256
        elif c[0] == '-': data[p] = (data[p] - len(c)) % 256
        elif c[0] == '>': p += len(c) ; tapeLenUpdater()
        elif c[0] == '<': p -= len(c) ; tapeLenUpdater()
        elif c[0] == '.': output.append(chr(data[p]))
        elif c[0] == ',': data[p] = getNextInput()
        elif c[0] == '[':
            if not data[p]:
                depth = 1
                while depth > 0:
                    i += 1
                    c = code[i]
                    if c == '[': depth += 1
                    elif c== ']': depth -= 1
        elif c == ']':
            if data[p]:
                depth = 1
                while depth > 0:
                    i -= 1
                    c = code[i]
                    if c == ']': depth += 1
                    elif c == '[': depth -= 1
        
        
        # Vizualisation commands/executions 
        #--------------------
        elif c[0] == '?': updateVizu(c)                             # check point found
        
        if ALL or SWITCH and c[0] != "?": updateVizu(c)             # Vizualisation for swithes (avoid double printing for check points)
        
        if c[0] == '!': SWITCH = not SWITCH                         # Update '!' swtich state
        #--------------------
        
        i += 1
    return ''.join(output)


#--------------------
#  LAUNCH THE TESTS 
#--------------------

EOF = chr(0)
for p,e in zip(inputs,exp):
    print("Input: ", p)
    act = brainFuckInterpreter(code, p+EOF)
    
    print("Input: ", p)                        # remainder of the input
    print(act, " should be ", e)               # print actual/expected before assertion
    assert act == e
    
    print("SUCCESS\n---\n")

changed id to string and check if result of the custom unique-method is correct

the problem now is, that the groovy-unique-method is not that slow as before....

Regular Expressions
Declarative Programming
Advanced Language Features
Fundamentals
Strings

This regular expression is a little lack luster. I think it could be improved to account for hyphens and apostraphes that are supposed to be apart of a word. The objective here is to not accidentally capture punctuation mistakes.

Code
Diff
  • wordCount=s=>s.trim().match(/[A-Za-z0-9]+/mg).length;
  • 1-wordCount=s=>s.trim().split(' ').length
    1+wordCount=s=>s.trim().match(/[A-Za-z0-9]+/mg).length;
Algorithms
Code
Diff
  • const getDividors = n => {
      
      let result = [];
    
      for (let i = 1; i <= Math.floor(Math.sqrt(n)); i += 1)
        if (n % i === 0) { result.push(i); if (n / i !== i) result.push(n / i) }
        
      return result; // output array won't be sorted
      
    }
  • 1-const getDividors = (n, result = []) => {
    1+const getDividors = n => {
    2+
    3+ let result = [];
    22
    3- for (let i = 1; i <= Math.floor(Math.sqrt(n)); i++)
    5+ for (let i = 1; i <= Math.floor(Math.sqrt(n)); i += 1)
    44 if (n % i === 0) { result.push(i); if (n / i !== i) result.push(n / i) }
    55
    66 return result; // output array won't be sorted
    77
    88 }
Graphs
Data Structures

Given any matrix, NxN or MxN we should be able to extract the inner matrix.

For example:
MxN [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] -> [[6, 7]]
NxN [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]] -> [[6, 7], [10, 11]]

innerMatrix = array => array
  .slice(1, array.length - 1)
  .map(row => row.slice(1, array[0].length - 1));
Algorithms
Code
Diff
  • const flatten = arr =>
      arr.reduce((acc, item) =>  acc.concat(Array.isArray(item) ? flatten(item) : item), []);
  • 11 const flatten = arr =>
    2- arr.reduce((acc, item) => acc.concat(Array.isArray(item) ? flatten(item) : [item]), []);
    2+ arr.reduce((acc, item) => acc.concat(Array.isArray(item) ? flatten(item) : item), []);
Search
Algorithms

Now it's even more prettier

Code
Diff
  • import java.util.*;
    
    class Node {
      int value;
      Node left;
      Node right;
      
      public Node(int value) {
        this.value = value;
      }
    }
    
    
    class BST {
      public static boolean search(Node root, int key) {   
          if (root == null)
            return false;
          if (root.value == key)
            return true;
          
          return root.value > key ? search(root.left, key) : search(root.right, key); 
      }
    }
  • 1010 }
    1111 }
    1212
    1313
    1414 class BST {
    1515 public static boolean search(Node root, int key) {
    16- if (root == null){
    17- return false;
    18- }else if(root.value == key) {
    16+ if (root == null)
    17+ return false;
    18+ if (root.value == key)
    1919 return true;
    20- } else{
    21- return root.value > key ? search(root.left, key) : search(root.right, key);
    22- }
    20+
    21+ return root.value > key ? search(root.left, key) : search(root.right, key);
    2323 }
    2424 }

Output numbers from 1 to x. If the number is divisible by 3, replace it with “Fizz”. If it is divisible by 5, replace it with “Buzz”. If it is divisible by 3 and 5 replace it with “FizzBuzz”.

(ns fizzbuzz.core)

(defn divisible-by? [divisor number]
  (zero? (mod number divisor)))
  
(defn fizzbuzz [x]
  (map #(cond 
          (divisible-by? 15 %) "FizzBuzz"
          (divisible-by? 5 %) "Buzz"
          (divisible-by? 3 %) "Fizz"
          :else %)
        (range 1 (inc x))))
Fundamentals
Strings
Code
Diff
  • const minutes = (n) => `${Math.trunc(n / 60)}:${("0" + (n % 60)).slice(-2)}`;
  • 1-function minutes(num){
    2- const minutes = num % 60
    3- const hours = (num - minutes)/60
    4- return `${hours}:${("0" + minutes).slice(-2)}`
    5-}
    1+const minutes = (n) => `${Math.trunc(n / 60)}:${("0" + (n % 60)).slice(-2)}`;
Code
Diff
  • import java.util.*;
    public class Average {
       public static int averageFinder(int[] arr) {
         return Arrays.stream(arr).sum() / arr.length;
       };
    }
  • 1+import java.util.*;
    11 public class Average {
    22 public static int averageFinder(int[] arr) {
    3- int total = 0;
    4- for(int num: arr){
    5- total += num;
    6- }
    7- return total / arr.length;
    8- }
    4+ return Arrays.stream(arr).sum() / arr.length;
    5+ };
    99 }

Faster than previsous versions by avoiding sorting and insertion of factor lists. Style fix (not is not a function)

Code
Diff
  • 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
  • 11 def divisors(n):
    2- fact = []
    2+ fact_lo = []
    3+ fact_hi = []
    33 for i in range(1, int(n**0.5) + 1):
    4- if not(n % i):
    5+ if not n % i:
    55 v = n // i
    66 if v != i:
    7- fact.insert(len(fact)//2,v)
    8- fact.insert(len(fact)//2,i)
    9- return fact
    8+ fact_hi.append(v)
    9+ fact_lo.append(i)
    10+ fact_lo.extend(reversed(fact_hi))
    11+ return fact_lo
Testing

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 and assert_approx_equals

Describe / It

  • Build the decorator version of describe and it, 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 and it blocks in the test output
  • Print the running times of describe and it blocks
  • Provide before and after for describe and it

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.
Code
Diff
  • 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)
    
  • 1-#from __future__ import print_function
    1+from __future__ import print_function
    2+import re, six
    3+range = six.moves.range
    4+
    22
    33 class AssertException(Exception):
    44 pass
    55
    66
    77 '''Fix the dreaded Unicode Error Trap'''
    8-_print = print
    9-def print(*args, sep=' ', end='\n'):
    10- from io import StringIO
    11- def _escape(s): return s.encode('ascii', 'xmlcharrefreplace').decode('ascii')
    12- sio = StringIO()
    13- _print(*args, sep=sep, end=end, file=sio)
    14- _print(_escape(sio.getvalue()))
    15- sio.close()
    11+def uni_print(*args, **kwargs):
    12+ from sys import stdout
    13+ sep = kwargs.get('sep', ' ')
    14+ end = kwargs.get('end', '\n')
    15+ file = kwargs.get('file', stdout)
    16+
    17+ def _replace(c):
    18+ if ord(c) >= 128: return u'&#{};'.format(ord(c))
    19+ return c
    20+ def _escape(s):
    21+ escaped = ''.join(_replace(c) for c in six.text_type(s))
    22+ escaped = re.sub(r'\\u([\da-f]{4})', lambda m: '&#{};'.format(int(m.group(1), 16)), escaped)
    23+ escaped = re.sub(r'\\U([\da-f]{8})', lambda m: '&#{};'.format(int(m.group(1), 16)), escaped)
    24+ return escaped
    25+
    26+ six.print_(*map(_escape, args), sep=_escape(sep), end=_escape(end), file=file)
    1616
    1717
    1818 def format_message(message):
    19- return message.replace("\n", "<:LF:>")
    30+ def _replace(c):
    31+ if ord(c) >= 65536: return r'\U' + hex(ord(c))[2:].zfill(8)
    32+ if ord(c) >= 128: return r'\u' + hex(ord(c))[2:].zfill(4)
    33+ return c
    2020
    2121
    2222 def expect(passed=None, message=None, allow_raise=False):
    23- if passed: print("\n<PASSED::>Test Passed")
    43+ if passed:
    44+ display('PASSED', 'Test Passed')
    2424 else:
    2525 message = message or "Value is not what was expected"
    26- print("\n<FAILED::>{0}".format(message))
    27- if allow_raise: raise AssertException(message)
    47+ display('FAILED', message)
    48+ if allow_raise:
    49+ raise AssertException(message)
    2828
    2929
    30-'''Fix the blocking asserts to non-blocking'''
    3131 def assert_equals(actual, expected, message=None, allow_raise=False):
    3232 equals_msg = "{0} should equal {1}".format(repr(actual), repr(expected))
    33- if message is None: message = equals_msg
    42-'''
    4343 def assert_not_equals(actual, expected, message=None, allow_raise=False):
    4444 equals_msg = "{0} should not equal {1}".format(repr(actual), repr(expected))
    45- if message is None: message = equals_msg
    46- else: message += ": " + equals_msg
    4747 expect(not (actual == expected), message, allow_raise)
    4848
    4949
    5050 def expect_error(message, function):
    5151 passed = False
    52- try: function()
    53- except: passed = True
    74+ try:
    75+ function()
    76+ except:
    77+ passed = True
    5959 def fail(message): expect(False, message)
    6969
    7070
    71-def display(type, message, label="", mode=""):
    72- print("\n<{0}:{1}:{2}>{3}".format(type.upper(), mode.upper(), label, format_message(message)))
    73-
    74-
    7575 '''
    76-Modern-Style Describe & It
    7777 Usage:
    7878 @describe('describe text')
    7979 def describe1():
    8585 from timeit import default_timer as timer
    8686 from traceback import format_exception
    8787 from sys import exc_info
    8888
    8989 def _timed_block_decorator(s, before=None, after=None):
    90- print('<{}::>{}'.format(opening_text, s))
    108+ display(opening_text, s)
    9191 def wrapper(func):
    9292 if callable(before): before()
    9393 time = timer()
    9494 try: func()
    9595 except:
    9696 fail('Unexpected exception raised')
    97- tb_str = ''.join(format_exception(*exc_info())).replace('\n', '<:LF:>')
    98- print('<ERROR::>' + tb_str)
    99- print('<COMPLETEDIN::>{}'.format(round((timer() - time) * 1000, 2)))
    115+ tb_str = ''.join(format_exception(*exc_info()))
    116+ display('ERROR', tb_str)
    117+ display('COMPLETEDIN', '{:.2f}'.format((timer() - time) * 1000))
    100100 if callable(after): after()
    101101 return wrapper
    102102 return _timed_block_decorator
    103103
    104104 describe = _timed_block_factory('DESCRIBE')
    105105 it = _timed_block_factory('IT')
    106106
    107107
    108108 '''
    109109 Timeout utility
    110110 Usage:
    111-with run_with_timeout(func, tuple_of_args, timeout_in_seconds) as run:
    112- Test.assert_equals(run.get(), expected_value)
    129+@timeout(sec)
    130+def some_tests():
    131+ any code block...
    113113 Note: Timeout value can be a float.
    114114 '''
    115-class run_with_timeout(object):
    116- def __init__(self, func, inputs, sec):
    117- from multiprocessing import Process, Queue
    118- def timeout_wrapper(func, inputs, q):
    124- def __enter__(self):
    125- self.p.start()
    126- return self
    127- def get(self):
    128- if self.result is None: self.result = self.q.get(timeout=self.sec)
    129- return self.result
    130- def __exit__(self, typ, val, traceback):
    131- self.q.close()
    132- self.p.terminate()
    133- self.p.join()
    134- if traceback: fail('Exceeded time limit of {:.3f} seconds'.format(self.sec))
    135- return True
    134+def timeout(sec):
    135+ def wrapper(func):
    136+ from multiprocessing import Process
    137+ process = Process(target=func)
    138+ process.start()
    139+ process.join(sec)
    140+ if process.is_alive():
    141+ fail('Exceeded time limit of {:.3f} seconds'.format(sec))
    142+ process.terminate()
    143+ process.join()
    144+ return wrapper
    136136
    137137
    138138 '''Old-style Fixture'''
    139139 describe('Old-style Describe')
    140140 it('Old-style It')
    141141 assert_equals(0, 0)
    142142 assert_equals(0, 1)
    143143 print('<COMPLETEDIN::>')
    144144 it('Old-style It 2')
    145145 assert_equals('a', 'a')
    146146 assert_equals('a', 'b')
    147147 print('<COMPLETEDIN::>')
    148148 print('<COMPLETEDIN::>')
    149149
    150150
    165165 assert_equals(1, 1, 'This is not run due to exception')
    166166 @it('Sample Testcase #1-3')
    167167 def sample_it_3():
    168168 assert_equals('abc', 'abc')
    169169 # source code doesn't support utf-8 chars, but you can at least log and test unicode
    170- assert_equals('\uac00 \ub098 \ub2e4', '\uac00 \ub098 \ub2e4')
    171- print('\uac00 \ub098 \ub2e4')
    172- assert_equals('\uac00 \ub098 \ub2e4', 'a b c')
    179+ assert_equals(u'\uac00 \ub098 \ub2e4', u'\uac00 \ub098 \ub2e4')
    180+ uni_print(1, 'a', u'\uac00 \ub098 \ub2e4', [2, 'b', u'\uac00'])
    181+ assert_equals(u'\uac00 \ub098 \ub2e4', 'a b c')
    173173
    174174
    175175 '''Sample Fixture #2: Featuring Before and After'''
    176176 @describe('Sample Fixture #2')
    177177 def sample_describe_2():
    178178 a = {0}
    179179 def before():
    180180 a.add(len(a))
    181181 @it('Sample Testcase #2-1', before=before, after=before)
    182182 def sample_it_1():
    183183 assert_equals(a, {0, 1})
    184184 @it('Sample Testcase #2-2')
    185185 def sample_it_2():
    186186 assert_equals(a, {0, 1, 2})
    187187
    188188
    189189 '''Sample Fixture #3: Featuring Timeout'''
    190190 @describe('Sample Fixture #3')
    191191 def sample_describe_3():
    192- def wait_count(n):
    193- for _ in range(n): pass
    194- return n
    195195 @it('Sample Testcase #3-1')
    196196 def sample_it_1():
    197- with run_with_timeout(wait_count, (100,), 0.01) as run:
    198- assert_equals(run.get(), 100)
    203+ @timeout(0.01)
    204+ def count():
    205+ for _ in range(100): pass
    206+ pass_()
    199199 @it('Sample Testcase #3-2')
    200200 def sample_it_2():
    201- with run_with_timeout(wait_count, (10 ** 10,), 0.01) as run:
    202- assert_equals(run.get(), 10 ** 10)
    209+ @timeout(0.01)
    210+ def count():
    211+ for _ in range(10**10): pass
    212+ pass_()
    203203
    204204
    205205 '''Sample Fixture #4: Featuring assert_approx_equals'''
    206206 @describe('Sample Fixture #4')
    207207 def sample_describe_4():
    208208 @it('Sample Testcase #4-1')
    209209 def sample_it_1():
    210210 assert_approx_equals(1, 1 + 1e-10, 1e-9)
    211211 assert_approx_equals(1, 1 + 1e-7, 1e-9)
    212212 assert_approx_equals(-1, -1 - 1e-10, 1e-9)
    213213 assert_approx_equals(-1, -1 - 1e-7, 1e-9)
    214214 @it('Sample Testcase #4-2')
    215215 def sample_it_2():
    216216 assert_approx_equals(0, 1e-10, 1e-9)
    217217 assert_approx_equals(0, 1e-7, 1e-9)
    218218 assert_approx_equals(0, -1e-10, 1e-9)
    219219 assert_approx_equals(0, -1e-7, 1e-9)
Testing

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 of describe and it blocks in the code
  • Properly close describe and it blocks in the test output
  • Print the running times of describe and it 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 and after for describe and it
  • 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.

Algorithms

All equal is a property of a whole list. One of possile ways is to use folds that are more natual way to cacluate/check value/property on a foldable structures.

Also algorithm has O(n) complexity

Code
Diff
  • module AllEqual where
    
    import Data.Foldable(foldl')
    
    allEqual :: [Int] -> Bool
    allEqual []     = True
    allEqual (x:xs) = foldl' (\b a -> b && (a==x)) True xs
  • 11 module AllEqual where
    2-import Data.List
    33
    4-allEqual :: [Int] -> Bool
    5-allEqual xs = length (nub xs) <= 1
    3+import Data.Foldable(foldl')
    4+
    5+allEqual :: [Int] -> Bool
    6+allEqual [] = True
    7+allEqual (x:xs) = foldl' (\b a -> b && (a==x)) True xs
Code
Diff
  • bool Or  ( bool a, bool b ){ return a ? a : b; }
    bool And ( bool a, bool b ){ return a ? b : false; }
    bool Xor ( bool a, bool b ){ return And(a,b) ? false: Or(a,b); }
  • 1-bool Or ( bool a, bool b ){ return a | b; }
    2-bool Xor ( bool a, bool b ){ return a ^ b; }
    3-bool And ( bool a, bool b ){ return a & b; }
    1+bool Or ( bool a, bool b ){ return a ? a : b; }
    2+bool And ( bool a, bool b ){ return a ? b : false; }
    3+bool Xor ( bool a, bool b ){ return And(a,b) ? false: Or(a,b); }
Fundamentals
Code
Diff
  • #include <stdio.h>
    
    int helloCplusplus(){
      return !puts("Hello Cplusplus\n");
    }
  • 11 #include <stdio.h>
    22
    33 int helloCplusplus(){
    4- puts("Hello Cplusplus\n");
    5- return 0;
    4+ return !puts("Hello Cplusplus\n");
    66 }
Code
Diff
  • -[------->+<]>-.-[->+++++<]>++.+++++++..+++.[--->+<]>-----.+++[->++<]>+.-[------>+<]>.+.[--->+<]>----.---------.----.+++++++.
  • 1->++++++[<++++++++++++>-]<.>>++++++++++[<++++++++++>-]<+.+++++++..+++.>>++++[<++++++++>-]<.<<-.>--------------.+.++++++++++++++++.---------.----.+++++++.
    1+-[------->+<]>-.-[->+++++<]>++.+++++++..+++.[--->+<]>-----.+++[->++<]>+.-[------>+<]>.+.[--->+<]>----.---------.----.+++++++.
Code
Diff
  • 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);
       
    }
    
  • 1-inline int multiply(int x, int y, int counter)
    1+inline float multiply(float number1, float number2 )
    22 {
    3- if (y <= 0)
    4- return 0;
    5-
    6- if (y == 1)
    7- return x;
    8-
    9- if (y & 0x1)
    10- return x + multiply(x, y - 1, 0);
    11-
    12- if (counter + counter <= y)
    13- return multiply(x + x, y >> 1, counter + counter);
    14- else
    15- return x + multiply(x, y - counter, 0);
    3+ float answer = 0;
    4+ while( number2 > 0 )
    5+ {
    6+ answer += number1;
    7+ number2--;
    8+ }
    9+ return answer;
    1616 }
    1717
    18-int squared(int number)
    12+
    13+float squared(float number)
    1919 {
    20- return multiply(number, number, 0);
    15+ if( number < 0 ) number = -number;
    16+
    17+ int decimal_positions = 0;
    18+ while( number - int(number) > 0.1 )
    19+ {
    20+ number = multiply(number, 10);
    21+ decimal_positions++;
    22+ }
    23+
    24+ float factor = number;
    25+
    26+ if( decimal_positions > 0 ) {
    27+ number = multiply(number,number);
    28+ switch (decimal_positions){
    29+ case 1: factor = 0.01; break;
    30+ case 2: factor = 0.001; break;
    31+ case 3: factor = 0.0001; break;
    32+ case 4: factor = 0.00001;
    33+ }}
    34+
    35+ return multiply(factor,number);
    36+
    2121 }

It is possible to exit before the end is reached, but in this example I added complexity to the model via the sorting.

Code
Diff
  • 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;
      }
    }
  • 1-import java.util.Map;
    2-import java.util.HashMap;
    1+import java.util.Arrays;
    33
    44 class MaxOccurence {
    55
    66
    77 public static int findMax(int[] nums) {
    8- HashMap<Integer,Integer> map = new HashMap<>();
    9- int lastBigVal = -1;
    10- int lastBigValIndx = -1;
    11-
    12- for(int i=0;i<nums.length;i++){
    13- map.putIfAbsent(nums[i],0);
    21- }
    22- }
    23- }
    24- return lastBigValIndx;
    7+ Arrays.sort(nums);
    8+ int countNumberMax = -1;
    9+ int numberMax = -1;
    10+
    11+ int currentCount = 0;
    12+ int currentNumber = nums.length>0?nums[0]:-1;
    13+
    21+ {
    22+ countNumberMax = currentCount;
    23+ numberMax = currentNumber;
    24+ }
    2525 }
    26-
    26+ else
    27+ {
    28+ currentCount = 1;
    29+ currentNumber = nums[i];
    30+ }
    31+
    32+ if(countNumberMax > nums.length/2 || countNumberMax > currentCount + nums.length - i)
    33+ {
    34+ break;
    35+ }
    36+ }
    37+
    38+ return numberMax;
    39+ }
    2727 }
Code
Diff
  • SELECT name 
    FROM greetings
    LIMIT 10;
  • 1-SELECT name FROM greetings
    2-WHERE greeting like '%ll%';
    1+SELECT name
    2+FROM greetings
    3+LIMIT 10;

caring about {[( and ingredinents with numbers like "vitamin B1"

Code
Diff
  • function glutenDetector(ingredients){
      const gluten = [
      "wheat",
      "wheat flour",
      "triticale",
      "barley",
      "rye",
      "brewer's yeast",
      "malt",
      "wheatberries",
      "durum",
      "emmer",
      "semolina",
      "spelt",
      "farina",
      "farro",
      "graham",
      "kamut",
      "einkorn"
      ];
      
      return ingredients
        .toLowerCase()
        .split(/[^\w\d]{2,}/)
        .some(x => gluten.includes(x));
    }
  • 1818 "kamut",
    1919 "einkorn"
    2020 ];
    2121
    2222 return ingredients
    2323 .toLowerCase()
    24- .split(/[,\s]+/)
    24+ .split(/[^\w\d]{2,}/)
    2525 .some(x => gluten.includes(x));
    2626 }
Code
Diff
  • SELECT * FROM current_catalog
  • 1-SELECT current_database();
    1+SELECT * FROM current_catalog
Parsing
Algorithms
Strings

Useful information concerning validity of email addresses can be found in this RFC document: https://tools.ietf.org/html/rfc5322

function validate(email) {
  return /(.+)@(.+){2,}\.(.+){2,}/.test(email);
}
#include <iostream>
#include <iterator>

int main() {
  static const int xs[] = {1, 2, 3};
  const auto ie = std::make_reverse_iterator(std::begin(xs));
  for (auto ix = std::make_reverse_iterator(std::end(xs)); ix != ie; ++ix)
    std::cout << *ix << ' ';
  std::cout << std::endl;
}
Mathematics
Algorithms
Numbers

You can declare Array with running numbers up by using [...Array(n).keys]. Then if you want it start from 1, you just increase array size then slice it of.

Code
Diff
  • const isPerfect = n => 
      [...Array(n).keys()].slice(1).filter(e => !(n % e)).reduce((a, b) => a + b) === n
  • 11 const isPerfect = n =>
    2- Array(n - 1).fill(1).map((e, i) => e + i).filter(e => n % e === 0).reduce((a, b) => a + b) === n
    2+ [...Array(n).keys()].slice(1).filter(e => !(n % e)).reduce((a, b) => a + b) === n
Code
Diff
  • # Method with three named arguments
    # https://robots.thoughtbot.com/ruby-2-keyword-arguments
    def c one: "one", two: "tow", three: "three"
    p "one: %s two: %s three: %s" % [one,two,three]
    
    end
    
    c  # calling without arguments
    c  two: "TWO2" # calling with one argument
    c  two: "2", one: 1111111 # Calling with 2 arguments with no order
    c(one: 1, two: 2, three: 3) # Passing 3 Named arguments
    c(two: 22, three: 333, one: 1 ) # Passing 3 Named arguments (mess the order)
    
    begin
      c  fore: "4" # calling with wrong argument
    rescue Exception => e 
      p e.message
      p e.class
    end
    begin
      #c (fore:"4") # calling with wrong argument
      # this lead to syntaxix error
    rescue Exception => e 
      puts("#{e.message}\n#{e.class}")
    end
    
    hash = {one: 'One', two: 'Two', three: 'Three'}
    c hash # calling with hash
    hash = {two: 'Two', three: 'Three', one: 'One', }
    c hash # calling with hash mess in order
    hash = { one: 'One', }
    c hash # calling with hash where not all argumetns listed
    
    # Super syntax
    hash = { two: '222', }
    c one: 1, **hash 
    # c one: 1, hash  # <== leads to error
    
    
    
    
    begin
      hash = { one: 'One', fore: "4" }
      c hash # calling with hash that contain pair unlisetd in named arguments
    rescue Exception => e 
      puts("#{e.message}\n#{e.class}")
    end
    
  • 1818 p e.class
    1919 end
    2020 begin
    2121 #c (fore:"4") # calling with wrong argument
    2222 # this lead to syntaxix error
    2323 rescue Exception => e
    24- p e.message
    25- p e.class
    24+ puts("#{e.message}\n#{e.class}")
    2626 end
    2727
    2828 hash = {one: 'One', two: 'Two', three: 'Three'}
    2929 c hash # calling with hash
    3030 hash = {two: 'Two', three: 'Three', one: 'One', }
    3131 c hash # calling with hash mess in order
    4242
    4343 begin
    4444 hash = { one: 'One', fore: "4" }
    4545 c hash # calling with hash that contain pair unlisetd in named arguments
    4646 rescue Exception => e
    47- p e.message
    48- p e.class
    46+ puts("#{e.message}\n#{e.class}")
    4949 end

It requires some optimization, but it works with just any number.

Code
Diff
  • import java.util.stream.IntStream;
    
    public class Primes {
      public static boolean isAPrime(int number) {
        return IntStream.range(2, number)
          .noneMatch(divider -> (number % divider) == 0); 
      }
    }
  • 1+import java.util.stream.IntStream;
    2+
    11 public class Primes {
    22 public static boolean isAPrime(int number) {
    3- if (number < 2 || (number % 2 == 0 && number != 2)) return false;
    4- for (int i = 3; i*i <= number; i += 2) {
    5- if (number % i == 0) return false;
    6- }
    7- return true;
    5+ return IntStream.range(2, number)
    6+ .noneMatch(divider -> (number % divider) == 0);
    88 }
    99 }

Just confirming that the Criterion testing framework is not supported in Objective-C in Codewars.

int add(int a, int b) {
  return a + b;
}

This is a response to the kumite https://www.codewars.com/kumite/5a4edf17d8e145968c00015e to show that it has an elegant solution for ruby using the compiled bash utility "tr"

It's my first kumite so I'm not sure if this is how to use it. Don't mind if I do!

Code
Diff
  • def pattern a,b
      a.tr(a,b)==b && b.tr(b,a)==a
    end
  • 1-def pattern(p,st):
    2- def encode(s):
    3- dic={} # dictionary to hold values from the input string
    4- num=0
    5- sn="" # a numerical string to hold the encoding
    6- for i in s:
    7- if i not in dic:
    8- dic[i]=num
    9- num+=1
    10- sn+=str(dic[i])
    11- return sn
    12- return encode(st)==encode(p)
    1+def pattern a,b
    2+ a.tr(a,b)==b && b.tr(b,a)==a
    3+end
Code
Diff
  • public static int euler(int x){
        int sum = 0;
            if(x%3==0||x%5==0){
                sum += x;}
                
        return sum ;
        
      }
  • 1-def euler(num):
    2- sum = 0
    3- for x in range(num):
    4- if x%3==0 or x%5==0:
    5- sum += x
    6- return sum
    1+public static int euler(int x){
    2+ int sum = 0;
    3+ if(x%3==0||x%5==0){
    4+ sum += x;}
    5+
    6+ return sum ;
    7+
    8+ }

Reduced, printing only simple stuff.

Code
Diff
  • bool alwaysTrue(int, int, int) {
      return true;
    }
  • 1-template <class... Args>
    2-bool alwaysTrue(Args&&...) {
    1+bool alwaysTrue(int, int, int) {
    33 return true;
    44 }

Although C++ templates can be a right pain in the arse when you're trying to model Peano numbers and their operations, they can come in handy when you want to define generic functions that work over a wide range of datatypes, especially higher-order functions that map a vector, for example.

using namespace std;

template<class T, class U> vector<U> vectorMap(vector<T> v, function<U (T)> f) {
  size_t size = v.size();
  vector<U> result (size);
  for (size_t i = 0; i < size; i++) result[i] = f(v[i]);
  return result;
}
template<class T> vector<T> vectorFilter(vector<T> v, function<bool (T)> f) {
  vector<T> result;
  for (size_t i = 0; i < v.size(); i++) if (f(v[i])) result.push_back(v[i]);
  return result;
}
template<class T, class U> U vectorReduce(vector<T> v, function<U (U, T)> f, U u) {
  U result = u;
  for (size_t i = 0; i < v.size(); i++) result = f(result, v[i]);
  return result;
}

Just a simple demonstration of how the contents of std::cout can be tested in a Kata by redirecting the stream to file I/O operations.

Credits and recommended resources:

#include <iostream>

void myFirstHelloWorld() {
  std::cout << "Goodbye World!" << std::endl;
}
Strings
Arrays

Not really useful, but calling replace with an array as replacement calls toString on it. It doesn't work the same using objects

const weird = 'asdf'.replace('a', [])
const weirdness = 'asdf'.replace('a', [1,2])
const volatile = 'asdf'.replace('a', {})

https://en.wikipedia.org/wiki/Quaternion

Quaternions are a number system that extends complex numbers. Like complex numbers, it has one real component, but quaternions have three imaginary components instead of just one. It retains many operations and properties of complex numbers, such as addition, subtraction and multiplication. However, due to its complexity, it has fewer properties than complex numbers, the most notable one being that multiplication is no longer commutative, i.e. given two quaternions p and q, pq /= qp in most cases. Quaternions form an algebraically closed system like the complex numbers, i.e. given any polynomial with quaternion coefficients, it is guaranteed that all roots of the polynomial will also be quaternions. Quaternions find a wide range of applications in other branches of mathematics, such as 3D rotations (in place of 3 by 3 matrices), and was even widely used in 3D geometry before the "invention" of the concept of the modern 3D vector (which provided simpler calculations for certain types of problems).

This Kumite contains a rudimentary definition/implementation of quaternions in Haskell with only a small fraction of possible operations and/or functions defined because I don't want to spoil a potential future Kata on quaternions (which I plan to author in Fortran once it arrives on Codewars, among other languages). Stay tuned ;)


Note to Haskell experts/mathematicians: I originally intended to create two constructors for the Quaternion data type, one initialized with 4 real numbers and one with 2 complex numbers (in agreement with the Cayley-Dickson construction of quaternions from complex numbers), but couldn't quite find a way to make all the operators work without defining an extra equation for each one (which doesn't feel pure but instead rather hacky). So feel free to remix this Kumite and add this functionality if you're feeling up for it, cheers :D

module Quaternions where

import Test.Hspec

data Quaternion a = Quaternion a a a a
  deriving (Eq, Show)

instance RealFloat a => Num (Quaternion a) where
  (Quaternion a1 b1 c1 d1) + (Quaternion a2 b2 c2 d2) = Quaternion (a1 + a2) (b1 + b2) (c1 + c2) (d1 + d2)
  (*) = error "Quaternion multiplication is not implemented here to minimize spoilers for my potential future Kata"
  abs (Quaternion a b c d) = Quaternion (sqrt $ a ^ 2 + b ^ 2 + c ^ 2 + d ^ 2) 0.0 0.0 0.0
  signum = error "Not implemented in this Kumite"
  fromInteger n = Quaternion (fromInteger n) 0.0 0.0 0.0
  negate (Quaternion a b c d) = Quaternion (negate a) (negate b) (negate c) (negate d)

instance RealFloat a => Fractional (Quaternion a) where
  (/) = error "General division is not well-defined for quaternions - please specify whether left division or right division is desired"
  recip = error "Not implemented in this Kumite to minimize spoilers"
  fromRational x = Quaternion (fromRational x) 0.0 0.0 0.0

infix 7 `ldiv`
infix 7 `rdiv`

ldiv, rdiv :: Quaternion a -> Quaternion a -> Quaternion a
ldiv = error "Left division of a quaternion: not implemented in this Kumite to minimize spoilers"
rdiv = error "Right division of a quaternion: not implemented in this Kumite to minimize spoilers"

main = hspec $ do
  describe "Quaternions" $ do
    it "should be able to be compared for equality" $ do
      Quaternion 1.0 2.0 4.0 3.0 `shouldBe` Quaternion 1.0 2.0 4.0 3.0
    it "should be able to be compared for inequality" $ do
      Quaternion 1.0 2.0 4.0 3.0 `shouldNotBe` Quaternion 2.0 1.0 4.0 3.0
    it "should support addition (of two quaternions)" $ do
      Quaternion 3.0 5.0 2.3 9.9 + Quaternion 4.3 5.5 17.3 1.2 `shouldBe` Quaternion 7.3 10.5 19.6 11.1
    it "should support finding the absolute value (of a quaternion)" $ do
      abs (Quaternion 3.0 4.0 12.0 0.0) `shouldBe` 13.0
    it "should support the construction of a quaternion from an integer" $ do
      fromInteger 5 `shouldBe` Quaternion 5.0 0.0 0.0 0.0
    it "should support negation (i.e. finding the additive inverse)" $ do
      negate (Quaternion 234.4432 43.5 (negate 5.0) (negate 55.5)) `shouldBe` Quaternion (negate 234.4432) (negate 43.5) 5.0 55.5
    it "should support the construction of a quaternion from a rational" $ do
      fromRational (negate 44235.948372) `shouldBe` Quaternion (negate 44235.948372) 0.0 0.0 0.0
Code
Diff
  • template< class T >
    void Swap( T& a, T& b ) 
    {
      a = (b - a) + (b = a);
    }
  • 1-#include <algorithm>
    2-#include <math.h>
    3-
    44 template< class T >
    55 void Swap( T& a, T& b )
    66 {
    7- std::swap(a, b);
    4+ a = (b - a) + (b = a);
    88 }

Returns the total occurrence count of given digit d in integer sequence of 0 to n, where each integer element is squared.

Code
Diff
  • public class CountTheDigit {
    	
    	public static int nbDig(int n, int d) {
        return n < 0 || d < 0 || d > 9 ? -1 : (int) java.util.stream.IntStream.range(0,n)
          .map(i->i*i)
          .mapToObj(String::valueOf)
          .flatMapToInt(String::chars)
          .filter(i->Character.digit((char)i,10)==d)
          .count();
        }
    	
    }
  • 11 public class CountTheDigit {
    2-
    3-
    44
    55 public static int nbDig(int n, int d) {
    6- String number ="";
    7- int count=0;
    8- for(int i=0; i<n; i++) {
    9- number=(i*i)+"";
    10- count += number.length() - number.replace(d+"", "").length();
    11- }
    12- return count;
    4+ return n < 0 || d < 0 || d > 9 ? -1 : (int) java.util.stream.IntStream.range(0,n)
    5+ .map(i->i*i)
    6+ .mapToObj(String::valueOf)
    7+ .flatMapToInt(String::chars)
    8+ .filter(i->Character.digit((char)i,10)==d)
    9+ .count();
    1313 }
    1414
    1515 }

A gozinta chain for n is a sequence {1,a,b,...,n} where each element properly divides the next.

There are eight gozinta chains for 12:
{1,12} ,{1,2,12}, {1,2,4,12}, {1,2,6,12}, {1,3,12}, {1,3,6,12}, {1,4,12} and {1,6,12}.

Let g(n) be the number of gozinta chains for n, so g(12)=8.
g(48)=48 and g(120)=132.

Given n, return the number of gozinta chains for g(n).

(Adapted from Project Euler, problem #548)

const g = (n) => {
  return "Good luck!"
}
Code
Diff
  • class Node:
        def __init__(self, x, Next, Prev):
            self.data = x
            self.next = Next
            self.prev = Prev
          
        
    class LinkedListIterator:
        def __init__(self, node):
            self.node = node
        
        def __iter__(self):
            return self
                
        def __next__(self):
            if not self.node:
                raise StopIteration
            value = self.node.data
            self.node = self.node.next        
            return value
    
           
    class LinkedList:
        def __init__(self, *x):
            self.start = None
            self.last = None
            self.length = 0
            self.addAll(x)
            
        def __iter__(self):
            return LinkedListIterator(self.start)
            
        def __str__(self):        
            out = '[ '+' '.join(map(str, self))+' ]'
            return out
        
        def clear(self):
            self.start = None
            self.last = None
            self.length = 0
            
        def add(self, x):
            if self.start == None:
                self.start = self.last = Node(x,None,None)
                self.length = 1
            else:
                prev = self.last
                self.last.next = self.last = Node(x,None,None)
                self.last.prev = prev
                self.length += 1
                
        def addAll(self, xs):        
            for i in xs:
                self.add(i)
        
        
        def remove_node(self, node):
            if not node.prev and node.next:            
                self.start = node.next
                node.next.prev = None
                self.length -= 1
                    
            elif not node.next and node.prev:            
                node.prev.next = None
                self.last = node.prev
                self.last.next = None
                self.length -= 1
                
            elif node.prev and node.next:
                node.prev.next = node.next
                node.next.prev = node.prev
                self.length -= 1
            else:
                self.clear()
                                
                
        def remove(self, x, remove_all = False):
            current = self.start        
            while current:
                if current.data == x:
                    self.remove_node(current)
                    if not remove_all:
                        break
                current = current.next
  • 11 class Node:
    2- def __init__(self,x,Next, Prev):
    2+ def __init__(self, x, Next, Prev):
    33 self.data = x
    44 self.next = Next
    55 self.prev = Prev
    6+
    7+
    8+class LinkedListIterator:
    9+ def __init__(self, node):
    10+ self.node = node
    11+
    12+ def __iter__(self):
    13+ return self
    14+
    15+ def __next__(self):
    16+ if not self.node:
    17+ raise StopIteration
    18+ value = self.node.data
    19+ self.node = self.node.next
    20+ return value
    66
    22+
    77 class LinkedList:
    88 def __init__(self, *x):
    99 self.start = None
    1010 self.last = None
    11- self.lenght = 0
    12- if x:
    13- for i in x:
    14- self.add(i)
    27+ self.length = 0
    28+ self.addAll(x)
    1515
    16- def __str__(self):
    17- if self.start != None:
    18- current = self.start
    19- out = '[ ' + str(current.data)
    20- while current.next != None:
    21- current = current.next
    22- out += ' '+ str(current.data)
    23- out += ' ]'
    24- return out
    30+ def __iter__(self):
    31+ return LinkedListIterator(self.start)
    2525
    33+ def __str__(self):
    34+ out = '[ '+' '.join(map(str, self))+' ]'
    35+ return out
    36+
    2626 def clear(self):
    27- self.__init__()
    38+ self.start = None
    39+ self.last = None
    40+ self.length = 0
    2828
    2929 def add(self, x):
    3030 if self.start == None:
    3131 self.start = self.last = Node(x,None,None)
    32- self.lenght += 1
    45+ self.length = 1
    3333 else:
    3434 prev = self.last
    3535 self.last.next = self.last = Node(x,None,None)
    3636 self.last.prev = prev
    37- self.lenght += 1
    50+ self.length += 1
    3838
    39- def addFew(self,*x):
    40- if x:
    41- for i in x:
    42- self.add(i)
    52+ def addAll(self, xs):
    53+ for i in xs:
    54+ self.add(i)
    4343
    69+ elif node.prev and node.next:
    70+ node.prev.next = node.next
    71+ node.next.prev = node.prev
    72+ self.length -= 1
    73+ else:
    74+ self.clear()
    75+
    4444
    45- def remove(self, x,remove_all = False):
    46- current = self.start
    47-
    48- for i in range(self.lenght):
    77+ def remove(self, x, remove_all = False):
    78+ current = self.start
    79+ while current:
    4949 if current.data == x:
    50- if current.prev == None:
    51- if current.next != None:
    52- self.start = current.next
    53- current.next.prev = None
    54- self.lenght -= 1
    81+ self.remove_node(current)
    82+ if not remove_all:
    7272 break
    7373 current = current.next

Given a number between 0-99999, the function number_to_english, return the same number pass to argument in letters.

Simple task, but the code is a little bit messy :D

Code
Diff
  • convertion = {
        0:'zero', 1:'one', 2:'two', 3:'three', 4:'four', 5:'five',
        6:'six', 7:'seven', 8:'eight', 9:'nine', 10:'ten',
        11:'eleven', 12:'twelve', 13:'thirteen', 14:'fourteen', 15:'fifteen',
        16:'sixteen', 17:'seventeen', 18:'eighteen', 19:'nineteen',
        20:'twenty', 30:'thirty', 40:'forty', 50:'fifty',
        60:'sixty', 70:'seventy', 80:'eighty', 90:'ninety'
    }
    
    
    def convert(num):
        if not 0 <= num <= 99999:
            return ''
    
        thousand, num = divmod(num, 1000)
        hundred, num = divmod(num, 100)
        ten, unit = divmod(num, 10)
        output = []
    
        if thousand:
            output += [convert(thousand), 'thousand']
        if hundred:
            output += [convertion[hundred], 'hundred']
    
        if ten == 1:
            output += [convertion[ten*10 + unit]]
        else:
            if ten:
                output += [convertion[ten*10]]
            if not output or unit:
                output += [convertion[unit]]
    
        return ' '.join(output)
    
    number_to_english = convert
  • 1-def mil(n):
    2- num={'0':'zero','1':'one','2':'two','3':'three','4':'four','5':'five','6':'six','7':'seven','8':'eight','9':'nine'}
    3- dec={'10':'ten','11':'eleven','12':'twelve','13':'thirteen','14':'fourteen','15':'fifteen','16':'sixteen','17':'seventeen','18':'eighteen','19':'nineteen'}
    4- dec_com={'20':'twenty','30':'thirty','40':'forty','50':'fifty','60':'sixty','70':'seventy','80':'eighty','90':'ninety'}
    5- mil="thousand"
    6- th=[]
    7- n_t=[x for x in n]
    8- for i in n_t:
    9- if len(n_t)==2:
    10- if i!='1' and n_t[1]=='0':
    11- th.append(dec_com[i+'0'])
    12- th.append(mil)
    13- break
    14- elif i=='1':
    15- th.append(dec[i+n_t[1]])
    16- th.append(mil)
    17- break
    18- else:
    19- th.append(dec_com[i+'0'])
    20- th.append(num[n_t[1]])
    21- th.append(mil)
    22- break
    23- else:
    24- th.append(num[i])
    25- th.append(mil)
    26- return th
    27-def cen(n):
    28- num={'0':'zero','1':'one','2':'two','3':'three','4':'four','5':'five','6':'six','7':'seven','8':'eight','9':'nine'}
    29- dec={'10':'ten','11':'eleven','12':'twelve','13':'thirteen','14':'fourteen','15':'fifteen','16':'sixteen','17':'seventeen','18':'eighteen','19':'nineteen'}
    30- dec_com={'20':'twenty','30':'thirty','40':'forty','50':'fifty','60':'sixty','70':'seventy','80':'eighty','90':'ninety'}
    31- cen="hundred"
    32- c=[]
    33- n_d=[x for x in n]
    34- for m in n_d:
    35- if n_d[0]!='0':
    36- c.append(num[m])
    37- c.append(cen)
    38- if n_d[1]=='0' and n_d[2]=='0':
    39- break
    40- elif n_d[1]=='0' and n_d[2]!='0':
    41- c.append(num[n_d[2]])
    42- break
    43- elif n_d[1]!='1' and n_d[2]=='0':
    44- c.append(dec_com[n_d[1]+'0'])
    45- break
    46- elif n_d[1]=='1':
    47- c.append(dec[n_d[1]+n_d[2]])
    48- break
    49- else:
    50- c.append(dec_com[n_d[1]+'0'])
    51- c.append(num[n_d[2]])
    52- break
    53- else:
    54- if n_d[1]=='0' and n_d[2]=='0':
    55- break
    56- elif n_d[1]=='0' and n_d[2]!='0':
    57- c.append(num[n_d[2]])
    58- break
    59- elif n_d[1]!='1' and n_d[2]=='0':
    60- c.append(dec_com[n_d[1]+'0'])
    61- break
    62- elif n_d[1]!='1' and n_d[2]!='0':
    63- c.append(dec_com[n_d[1]+'0'])
    64- c.append(num[n_d[2]])
    65- break
    66- elif n_d[1]=='1':
    67- c.append(dec[n_d[1]+n_d[2]])
    68- break
    69-
    70- return c
    71-def number_to_english(n):
    72- num={0:'zero',1:'one',2:'two',3:'three',4:'four',5:'five',6:'six',7:'seven',8:'eight',9:'nine'}
    73- dec={10:'ten',11:'eleven',12:'twelve',13:'thirteen',14:'fourteen',15:'fifteen',16:'sixteen',17:'seventeen',18:'eighteen',19:'nineteen'}
    74- dec_com={20:'twenty',30:'thirty',40:'forty',50:'fifty',60:'sixty',70:'seventy',80:'eighty',90:'ninety'}
    75- th=[]
    76- c=[]
    77- m='{0:,}'.format(n)
    78- m=m.split(",")
    79- try:
    80- if n<0 or type(n)==float or n>99999:
    81- pass
    82- elif n<10:
    83- c.append(num[n])
    84- elif n<20:
    85- c.append(dec[n])
    86- elif n%10==0 and n<99:
    87- c.append(dec_com[n])
    88- elif n<99:
    89- k=list(str(n))
    90- c.append(dec_com[int(k[0]+'0')])
    91- c.append(num[int(k[1])])
    92- else:
    93- c=cen(m[1])
    94- th=mil(m[0])
    95- except IndexError:
    96- if n<0 or type(n)==float or n>99999:
    97- pass
    98- elif n<10:
    99- c.append(num[n])
    100- elif n<20:
    101- c.append(dec[n])
    102- elif n%10==0 and n<99:
    103- c.append(dec_com[n])
    104- elif n<99:
    105- k=list(str(n))
    106- c.append(dec_com[int(k[0]+'0')])
    107- c.append(num[int(k[1])])
    108- else:
    109- c=cen(m[0])
    110- t=[]
    111- t.extend(th)
    112- t.extend(c)
    113- return " ".join(t)
    1+convertion = {
    2+ 0:'zero', 1:'one', 2:'two', 3:'three', 4:'four', 5:'five',
    3+ 6:'six', 7:'seven', 8:'eight', 9:'nine', 10:'ten',
    4+ 11:'eleven', 12:'twelve', 13:'thirteen', 14:'fourteen', 15:'fifteen',
    5+ 16:'sixteen', 17:'seventeen', 18:'eighteen', 19:'nineteen',
    6+ 20:'twenty', 30:'thirty', 40:'forty', 50:'fifty',
    7+ 60:'sixty', 70:'seventy', 80:'eighty', 90:'ninety'
    8+}
    9+
    10+
    11+def convert(num):
    12+ if not 0 <= num <= 99999:
    13+ return ''
    14+
    15+ thousand, num = divmod(num, 1000)
    16+ hundred, num = divmod(num, 100)
    17+ ten, unit = divmod(num, 10)
    18+ output = []
    19+
    20+ if thousand:
    21+ output += [convert(thousand), 'thousand']
    22+ if hundred:
    23+ output += [convertion[hundred], 'hundred']
    24+
    25+ if ten == 1:
    26+ output += [convertion[ten*10 + unit]]
    27+ else:
    28+ if ten:
    29+ output += [convertion[ten*10]]
    30+ if not output or unit:
    31+ output += [convertion[unit]]
    32+
    33+ return ' '.join(output)
    34+
    35+number_to_english = convert
Code
Diff
  • namespace Currying {
      using System;
    
      public static class Functions {
        public static Func<TOut1> Curry<TOut1>(this Func<TOut1> fn) => () => fn();
        public static Func<TIn1, TOut2> Curry<TIn1, TOut2>(this Func<TIn1, TOut2> fn) => a => fn(a);
        public static Func<TIn1, Func<TIn2, TOut3>> Curry<TIn1, TIn2, TOut3>(this Func<TIn1, TIn2, TOut3> fn) => a => b => fn(a, b);
        public static Func<TIn1, Func<TIn2, Func<TIn3, TOut4>>> Curry<TIn1, TIn2, TIn3, TOut4>(this Func<TIn1, TIn2, TIn3, TOut4> fn) => a => b => c => fn(a, b, c);
        public static Func<TIn1, Func<TIn2, Func<TIn3, Func<TIn4, TOut5>>>> Curry<TIn1, TIn2, TIn3, TIn4, TOut5>(this Func<TIn1, TIn2, TIn3, TIn4, TOut5> fn) => a => b => c => d => fn(a, b, c, d);
        public static Func<TIn1, Func<TIn2, Func<TIn3, Func<TIn4, Func<TIn5, TOut6>>>>> Curry<TIn1, TIn2, TIn3, TIn4, TIn5, TOut6>(this Func<TIn1, TIn2, TIn3, TIn4, TIn5, TOut6> fn) => a => b => c => d => e => fn(a, b, c, d, e);
      }
    }
  • 1-var test = new Currying.TestCurrying();
    2-test.testSequential();
    3-test.testRandom();
    1+namespace Currying {
    2+ using System;
    3+
    4+ public static class Functions {
    5+ public static Func<TOut1> Curry<TOut1>(this Func<TOut1> fn) => () => fn();
    6+ public static Func<TIn1, TOut2> Curry<TIn1, TOut2>(this Func<TIn1, TOut2> fn) => a => fn(a);
    7+ public static Func<TIn1, Func<TIn2, TOut3>> Curry<TIn1, TIn2, TOut3>(this Func<TIn1, TIn2, TOut3> fn) => a => b => fn(a, b);
    8+ public static Func<TIn1, Func<TIn2, Func<TIn3, TOut4>>> Curry<TIn1, TIn2, TIn3, TOut4>(this Func<TIn1, TIn2, TIn3, TOut4> fn) => a => b => c => fn(a, b, c);
    9+ public static Func<TIn1, Func<TIn2, Func<TIn3, Func<TIn4, TOut5>>>> Curry<TIn1, TIn2, TIn3, TIn4, TOut5>(this Func<TIn1, TIn2, TIn3, TIn4, TOut5> fn) => a => b => c => d => fn(a, b, c, d);
    10+ public static Func<TIn1, Func<TIn2, Func<TIn3, Func<TIn4, Func<TIn5, TOut6>>>>> Curry<TIn1, TIn2, TIn3, TIn4, TIn5, TOut6>(this Func<TIn1, TIn2, TIn3, TIn4, TIn5, TOut6> fn) => a => b => c => d => e => fn(a, b, c, d, e);
    11+ }
    12+}
Code
Diff
  • module Developer
      def are_you_dev?
        true
      end
    end
    
    class Ivan
      def give_me_beer?
        true
      end
    end
    class Andy < Ivan
    end
    
    class Vasa < Andy
      include Developer
    end
    
    class Kolya < Vasa
    end
    
    
  • 1+module Developer
    2+ def are_you_dev?
    3+ true
    4+ end
    5+end
    6+
    11 class Ivan
    22 def give_me_beer?
    33 true
    44 end
    55 end
    66 class Andy < Ivan
    77 end
    88
    99 class Vasa < Andy
    16+ include Developer
    1010 end
    1111
    1212 class Kolya < Vasa
    1313 end
    1414

Need to find amount of natural number that can be generated from an array of digit characters.

1) Answers is one number: total amount of natural numbers can be generated by moving elements of the array.
2) Each number have N digits, where N is an Array size.
3) Each number use each charachter from an Array oney once.

This code needs optimization.

P.S. Question from: https://stackoverflow.com/questions/47616564/find-amount-of-natural-numbers-generated-from-array-of-digit-characters

def g(a)
  answer = a.permutation(a.size)
  .select{|x| x.join.to_i.to_s.split("").size == a.size }
  .to_a.uniq.size
  answer
end

Make hahahah progamm

Improve it for different x inputs.

def ha x
  "Ha" + "-ha" * (x - 1)
end

Try to make match in ruby to work like js mathc.

def slot s
  p "ONE scan"
  p "input: %s" % s
  p "output " + s.scan(/!+|\?+/).inspect
  
  p "TWO scan"
  p "input: %s" % s
  p "output " + s.scan(/([?!])\1*/).inspect
  
  p "ONE match"
  p "input: %s" % s
  p "match"
  s.match(/!+|\?+/).to_a.each{|x| p x}
  p "TWO  match"
  p "input: %s" % s
  p "match"
  s.match(/([?!])\1*/).to_a.each{|x| p x}
end

slot("!!!??")

Compare JS and Ruby REEGEX

RUBY s.scan(/!+|\?+/).inspect == JS s.match(/!+|\?+/g)

RUBY s.scan(/([?!])\1*/) != JS s.match(/([?!])\1*/g)

https://gist.github.com/lbvf50mobile/4b3cd312ad411e47582af40c7cbd4e05/edit

let slot = s => {
  console.log("ONE")
  console.log("input ", s)
  console.log("output" ,s.match(/!+|\?+/g))
  
  console.log("ONE")
  console.log("input ", s)
  console.log("output", s.match(/([?!])\1*/g))
}

slot("!!!??")