# balanced word

We can assign a value to each character in a word, based on their position in the alphabet (a = 1, b = 2, … , z = 26). A balanced word is one where the sum of values on the left-hand side of the word equals the sum of values on the right-hand side. For odd length words, the middle character (balance point) is ignored.

Write a function that returns true if the word is balanced, and false if it’s not.

Crystal:

``````def split_word(w : String) : Array(String)
is_even = w.size % 2 == 0
middle = (w.size / 2).to_i
if is_even
return [w[0...middle], w[middle..]]
end
[w[0...middle], w[middle + 1..]]
end

def calc_value(w : String)
chars = "a".."z"
w.split("").map { |ch| chars.index!(ch) + 1 }.sum
end

def balanced(w : String)
return true if w.reverse == w
end``````

Nothing special here. Perhaps of note: `..` and `...` represent different ranges in Crystal. `..` is inclusive, while `...` is exclusive. E.g. `"a"..."z"` would actually only give us “a” to “y”, so it’s something to look out for.

``````import std/[strutils, sequtils, math, algorithm]

type WordArr = array[2, string]

proc splitWord(w: string): WordArr =
let isEven = w.len mod 2 == 0
let mid = w.len div 2
if isEven: return [w[0..<mid], w[mid..^1]]
return [w[0..<mid], w[mid+1..^1]]

proc calcScore(a: string): int =
let lc = LowercaseLetters.toSeq
let chars = a.toSeq
chars.mapIt(lc.find(it) + 1).sum

func balanced(w: string): bool =
if w.toSeq.reversed == w.toSeq: return true
let
split = splitWord(w)
tail = split[^1]

Nim gives us some nice ways to index arrays / sequences. `..<` means exclusive, while `..` is inclusive (I like this better than Crystal’s version - it’s easier to remember). We’ve got `^1`, which is shorthand for `arr.len - 1`. Instead of creating a range, we use `LowercaseLetters` from the standard lib’s `strutils`. It provides us with a set, which we then convert into a sequence so that we can lookup indexes.

For this kata, we had to import quite a few modules from the standard library. I’m not too sure how to feel about that - on the one hand, I suppose it’s a good thing that we import something explicitly when we need it - on the other, I suppose you would need some degree of familiarity with the stlib, or at least know where to look.

Raku:

``````sub split-word(Str \$w) {
my \$mid = \$w.comb.elems div 2;
return \$w.substr(0..^\$mid), \$w.substr(\$mid + 1) if \$w.comb.elems mod 2;
return \$w.substr(0..^\$mid), \$w.substr(\$mid);
}

sub calc-score(Str \$w) {
my \$map = "a".."z";
[+] \$w.comb.map({\$map.first(\$_, :k) + 1});
}

sub balanced(Str \$w) {
return True if \$w.comb.reverse ~~ \$w.comb;
}``````

In Raku, we can use the `^` to denote an exclusive range, but otherwise, the implementation is quite similar.

Last one, Javascript:

``````function splitWord(w: string) {
const mid = Math.floor(w.length / 2);
const isEven = w.length % 2 == 0;
if (isEven) return [w.slice(0, mid), w.slice(mid)];
return [w.slice(0, mid), w.slice(mid + 1)];
}

function calcScore(w: string) {
const chars = "abcdefghijklmnopqrstuvwxyz";
return w
.split("")
.map((c) => chars.indexOf(c) + 1)
.reduce((acc, curr) => acc + curr);
}

function balanced(w: string) {
if (w.split("").reverse().join("") === w) return true;