Skip to content

Instantly share code, notes, and snippets.

Created August 11, 2013 11:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/6204468 to your computer and use it in GitHub Desktop.
Save anonymous/6204468 to your computer and use it in GitHub Desktop.
#pragma indent
using Nemerle.Collections;
using Nemerle.Extensions;
using System;
using System.Collections.Generic;
using System.Console;
using System.IO;
using System.Linq;
using System.Math;
using System.Text;
module Program
Main(args : array[string]) : void
def costs = Dictionary() <- [
'А'=1, 'Б'=5, 'В'=2, 'Г'=4, 'Д'=4, 'Е'=1, 'Ж'=6, 'З'=4, 'И'=1, 'Й'=5, 'К'=3,
'Л'=2, 'М'=2, 'Н'=1, 'О'=1, 'П'=3, 'Р'=2, 'С'=2, 'Т'=2, 'У'=3, 'Ф'=7, 'Х'=5,
'Ц'=7, 'Ч'=5, 'Ш'=4, 'Щ'=0, 'Ъ'=0, 'Ы'=4, 'Ь'=5, 'Э'=10,'Ю'=4, 'Я'=3 ]
def dict = GetDict(if(args.Any()) args[0] else"dict.txt", Encoding.GetEncoding(1251), 3)
def map = GetLines()
def wordament = Wordament(costs, dict)
wordament.GetWords(map).Distinct().OrderBy(wordament.WordCost).Iter(WriteLine)
GetDict(path : string, encoding: Encoding, minWordLen : int) : Seq[string]
File.ReadLines(path, encoding) \
.Select(l => l.Trim().Split(array[' '], StringSplitOptions.RemoveEmptyEntries)[0].ToUpper()) \
.Where(w => w.Length >= minWordLen)
GetLines() : Seq[string]
mutable len = -1
for(mutable line = ReadLine(); len < 0 || !string.IsNullOrEmpty(line); line = ReadLine())
if(string.IsNullOrEmpty <| line)
WriteLine <| "Line expected"
else
when(len < 0) len = line.Length
if(len != line.Length) WriteLine <| $"Exprected length $len" else yield line
class Wordament
dict : Trie
costs : IReadOnlyDictionary[char, int]
public this(costs : IReadOnlyDictionary[char, int], dict : Seq[string])
this.costs = costs
this.dict = Trie(dict)
public WordCost(word : string) : int
word.ToCharArray().Sum(ch => if(costs.ContainsKey <| ch) costs[ch] else 0)
public GetWords(map : Seq[string]) : Seq[string]
def map = map.Select(s => s.ToUpper().ToCharArray()).ToArray()
def starts = $[(x, y) | y in $[0..map.Length - 1], x in $[0..map[y].Length - 1]]
starts.SelectMany(iterMap(map, [], dict.Root, string.Empty, _, _))
iterMap(map : array[array[char]], visited : list[int*int],
node : Trie.TrieNode, str : string, x : int, y : int) : Seq[string]
def ch = map[y][x]
when(node.Childs.ContainsKey <| ch)
def node' = node.Childs[ch]
def str' = str + ch
when(node'.IsLeaf) yield str'
def visited' = (x, y)::visited
for(mutable y' = Max(y - 1, 0); y' <= Min(map.Length - 1 , y + 1); y'++)
for(mutable x' = Max(x - 1, 0); x' <= Min(map[y'].Length - 1, x + 1); x'++)
when(!visited.Contains((x', y')) && node'.Childs.ContainsKey(map[y'][x']))
foreach(word in iterMap(map, visited', node', str', x', y'))
yield word
class Trie
public class TrieNode
public Childs : Dictionary[char, TrieNode] = Dictionary()
public mutable IsLeaf : bool
public Root : TrieNode = TrieNode()
public this(strs : Seq[string])
foreach(str in strs)
mutable node = Root
foreach(ch in str.ToCharArray())
when(!node.Childs.ContainsKey(ch))
node.Childs.Add(ch, TrieNode())
node = node.Childs[ch]
node.IsLeaf = true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment