Split a word into parts with equal scores Assuming A=1, B=2... Z=26, and the value of a word is the sum of these letter values, it is possible to split some words into two pieces such that they have equal values.

For example, "wordsplit" can be broken into two pieces like so: ordsl wpit, because o+r+d+s+l = w+p+i+t.

This was a challenge given to us by my computing teacher - it is an old Lionhead Studios challenge, apparently. I have solved it in Python, and will post my answer shortly.

Challenge: The shortest program which can list all the possible splits which have equal scores. Note that it only has to list one for each group of letters - ordsl wpit is the same as rdosl wtip, for example. It is easier to list them in the order they come in the word.

Bonus:


If you highlight pairs where both words are valid English words (or some permutation of the letters is), using a word list of some kind. (This could be done by placing an asterisk next to each or some other method, but make it clear.)
Adding the option for removing duplicates (this should not be the default.)
Supporting more than two splits, for example, three, four or even n-way splits.
Perl, 115 118 123

@_=~/./g;for$i(1..1&lt;&lt;@_){$l=$
r;$i&amp;1&lt;&lt;$_?$l:$r+=64-ord$_[$_
]for 0..$#_;$l-$r||$i&amp;1&lt;&lt;$_&amp;&amp;
print$_[$_]for 0..$#_;say""}


Run with perl -nE '&lt;code goes here&gt;'. That 'n' is counted in the code size.

Respaced:

@_ = /./g;
for $i (1 .. 1&lt;&lt;@_) {
  $l = $r;
  $i &amp; 1&lt;&lt;$_ ? $l : $r -= 64 - ord $_[$_] for 0 .. $#_;

  $l - $r      ||
  $i &amp; 1&lt;&lt;$_   &amp;&amp;
  print $_[$_]
    for 0 .. $#_;

  say ""
}


With comments and variable names:

# split a line of input by character
@chars = /./g;

# generate all binary masks of same length
for $mask (1 .. 1&lt;&lt;@_) {

  # start at "zero"
  $left_sum = $right_sum;

  # depending on mask, choose left or right count
  # 1 -&gt; char goes left; 0 -&gt; char goes right
  $mask &amp; 1&lt;&lt;$_ ? $left_sum : $right_sum
    -= 64 - ord $chars[$_]   # add letter value
      for 0 .. $#chars;      # for all bits in mask

  # if left = right
  $left_sum - $right_sum ||

  # if character was counted left (mask[i] = 1)
  $mask &amp; 1&lt;&lt;$_          &amp;&amp;

  # print it
  print $chars[$_]

  # ...iterating on all bits in mask
    for 0 .. $#chars;

  # newline
  say ""
}


Some of the tricks used:


1..1&lt;&lt;@_ covers the same bit range as 0..(1&lt;&lt;@_)-1 , but is shorter. (note that considering the problem from further away, including the range boundaries multiple times wouldn't result in a wrong output anyway)
$left_range and $right_range aren't reset to actual "0" numeric zero: since we just accumulate and compare them in the end, all we need is them to start at the same value.
subtracting 64-ord$_[$_] instead of adding ord$_[$_]-64 wins an invisible character: since it ends with a delimiter, it makes the space before for unnecessary.
Perl lets you assign to a variable determined by the ternary conditional operator: cond ? var1 : var2 = new_value.
boolean expressions chained with &amp;&amp; and || are used instead of proper conditionals.
$l-$r is shorter than $l!=$r
will output a newline even on splits that don't balance.  Empty lines are ok by the rules!  I asked!