Task: Word break problem





Java: import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class WordBreak {

    public static void main(String[] args) {
        List<String> dict = Arrays.asList("a", "aa", "b", "ab", "aab");
        for ( String testString : Arrays.asList("aab", "aa b") ) {
            List<List<String>> matches = wordBreak(testString, dict);
            System.out.printf("String = %s, Dictionary = %s.  Solutions = %d:%n", testString, dict, matches.size());
            for ( List<String> match : matches ) {
                System.out.printf(" Word Break = %s%n", match);
            }
            System.out.printf("%n");
        }
        dict = Arrays.asList("abc", "a", "ac", "b", "c", "cb", "d");
        for ( String testString : Arrays.asList("abcd", "abbc", "abcbcd", "acdbc", "abcdd") ) {
            List<List<String>> matches = wordBreak(testString, dict);
            System.out.printf("String = %s, Dictionary = %s.  Solutions = %d:%n", testString, dict, matches.size());
            for ( List<String> match : matches ) {
                System.out.printf(" Word Break = %s%n", match);
            }
            System.out.printf("%n");
        }
    }
    
    private static List<List<String>> wordBreak(String s, List<String> dictionary) {
        List<List<String>> matches = new ArrayList<>();
        Queue<Node> queue = new LinkedList<>();
        queue.add(new Node(s));
        while ( ! queue.isEmpty() ) {
            Node node = queue.remove();
            
            if ( node.val.length() == 0 ) {
                matches.add(node.parsed);
            }
            else {
                for ( String word : dictionary ) {
                    
                    if ( node.val.startsWith(word) ) {
                        String valNew = node.val.substring(word.length(), node.val.length());
                        List<String> parsedNew = new ArrayList<>();
                        parsedNew.addAll(node.parsed);
                        parsedNew.add(word);
                        queue.add(new Node(valNew, parsedNew));
                    }
                }
            }
        }
        return matches;
    }
    
    private static class Node {
        private String val;  
        private List<String> parsed;  
        public Node(String initial) {
            val = initial;
            parsed = new ArrayList<>();
        }
        public Node(String s, List<String> p) {
            val = s;
            parsed = p;
        }
    }

}



Python: 

from itertools import (chain)



def stringParse(lexicon):
    
    return lambda s: Node(s)(
        tokenTrees(lexicon)(s)
    )



def tokenTrees(wds):
    
    def go(s):
        return [Node(s)([])] if s in wds else (
            concatMap(nxt(s))(wds)
        )

    def nxt(s):
        return lambda w: parse(
            w, go(s[len(w):])
        ) if s.startswith(w) else []

    def parse(w, xs):
        return [Node(w)(xs)] if xs else xs

    return lambda s: go(s)



def showParse(tree):
    
    def showTokens(x):
        xs = x['nest']
        return ' ' + x['root'] + (showTokens(xs[0]) if xs else '')
    parses = tree['nest']
    return tree['root'] + ':\n' + (
        '\n'.join(
            map(showTokens, parses)
        ) if parses else ' ( Not parseable in terms of these words )'
    )




def main():
    

    lexicon = 'a bc abc cd b'.split()
    testSamples = 'abcd abbc abcbcd acdbc abcdd'.split()

    print(unlines(
        map(
            showParse,
            map(
                stringParse(lexicon),
                testSamples
            )
        )
    ))





def Node(v):
    
    return lambda xs: {'type': 'Node', 'root': v, 'nest': xs}



def concatMap(f):
    
    return lambda xs: list(
        chain.from_iterable(map(f, xs))
    )



def unlines(xs):
    
    return '\n'.join(xs)



if __name__ == '__main__':
    main()