title: Draw the Stickman Wars

text:
# Question
Title: Draw the Stickman Wars
Picture of me drafting this challenge with my advanced drawing skills.

## Background

The Stickman wars happened long ago, when Earth's dominant species was made of nothing but sticks. Historians regret the fact that there were no painters or cameras back then, we could use some pictures of that war in today's history books. That's where your coding powers become useful. Stickmen are very easily drawed and Historians managed to find some data about how many stickmen fought the wars¹. Now it's up to you to recreate an image of the moment right before the war began!

Here are the brave stickmen involved in the war:

```
  O  /
|/|\/
| |
 / \  Swordsman

 O A
/|\|
 | |
/ \| Spearman

   .
 .' *.
 ' O *
' \|/ .
.  |  *
'./ \*. Mage

 O
/|\
 |
/ \ Villager

 O
/|\
/ \ Infant

```

**Input**

Receive via stdin or equivalent a representation of every stickman who appeared on each side of the battlefield. For example, if two Swordmen fought on the right side and two spearmen on the left side, your input can be `{Sword: 2}, {Spear: 2}`, `[2,0,0,0,0], [0,2,0,0,0]` or a `"WW", "SS"`.

**Output**

A representation of every brave stickmen in a battle field, according to the rules below. It can be shown on stdout or saved to a file, whatever rocks your boat.

**Rules**

1. On the left side will be every stickmen of the first array/string/object your program received.
2. Those stickmen must look exactly like the ones shown before on this question.
3. The order of the left side army must be `Infants Villagers Mages Swordsmen Spearmen`.
4. The right side army will behave just the same, but with the characters and the order mirrored.
5. Each stickman will be separated by 1 space.
6. Each class will be separated by 3 spaces.
7. The armies will be separated by 8 spaces.
8. Since stickmen don't fly, you must draw the ground using hyphen-minuses `-`.
9. The ground must end on the same column the last stickman of the right army ends.

**Example**

Let's assume my program expects two arrays with length 5 and each value in the array represents, in order, `Infants Villagers Mages Swordsmen Spearmen`.

Input: \[1,1,2,3,1\] \[0,0,1,1,1\]

```
               .       .                                                           .
             .' *.   .' *.                                                       .* '.
       O     ' O *   ' O *      O  /   O  /   O  /    O A        A O   \  O      * O '
 O    /|\   ' \|/ . ' \|/ .   |/|\/  |/|\/  |/|\/    /|\|        |/|\   \/|\|   . \|/ '
/|\    |    .  |  * .  |  *   | |    | |    | |       | |        | |      | |   *  |  .
/ \   / \   './ \*. './ \*.    / \    / \    / \     / \|        |/ \    / \    .*/ \'.
---------------------------------------------------------------------------------------

```

**Final Considerations**

Please note that standard loopholes apply and that the mage is completely asymmetrical just because.

The result of most upvoted answer will be the "cover image" of this challenge. The shortest answer by the end of the month (08/31/2014) will be selected as the winner.

This is , so the shortest code, in bytes, wins.

---

¹Citation needed

# Answer
# JavaScript (E6) 336 ~~344 356 369 424 478 522 570~~

**Edit 6** Last edit was buggy. Bug fix and shortened. That's all I hope.

**Edit 5** Finally found a way to get rid of multiply by 23 - bothered me from start. Plus another change to the input (@William shout when it's too much). Now the function expects one array parameter, containing 2 subarrays. Without this change it's 349 - still an improvement

**Edit 4** Shaved some more bytes and a little change to input format. With the new input format a missing class is represented as an empty array element. So `D([1,,2,3,1],[,3,1,1,2])` instead of `D([1,0,2,3,1],[0,3,1,1,2])`. I think it still obeys the rules.

**Edit 3** Golfed more. No changes to the algorithm, but abusing a lot of array.map and local functions to avoid for loops.

**Edit 2** String compression, the right way ...

**Edit** Added string compression, a lot of work and not much gained. Now the mirror stickmen are generated from a template, not stored.

Made a few tries, first running. ~~To be golfed.~~ ~~NB Kolmogorow-business still to be tackled.~~

**Test** In FireFox console. ~~Change 'return' with~~ Add 'alert(...)' to have an output statement (albeit not useful at all)

`console.log(D([[1,,2,3,1],[,3,1,1,2]]))`

*Output*

```
         .       .                                                                 .
       .' *.   .' *.                                                             .* '.
       ' O *   ' O *      O  /   O  /   O  /    O A        A O  A O    \  O      * O '     O   O   O
 O    ' \|/ . ' \|/ .   |/|\/  |/|\/  |/|\/    /|\|        |/|\ |/|\    \/|\|   . \|/ '   /|\ /|\ /|\
/|\   .  |  * .  |  *   | |    | |    | |       | |        | |  | |       | |   *  |  .    |   |   |
/ \   './ \*. './ \*.    / \    / \    / \     / \|        |/ \ |/ \     / \    .*/ \.'   / \ / \ / \
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

```

**Golfed Code**

```
D=a=>
  (J=v=>v.join(''))((l=[r=n=' ',3,6,13,19,23]).map(_=>f=(F=f=>J(a[f].map((c,q)=>
  ("9.299.' *.87O2' O *3O21 O A O 1|0' 0|1 .|1|01 1|0|1|0 | .2|2*| |4| |1 01 0'.1 0*. 1 021 0|"[R='replace'](/[2-9]/g,x=>n.repeat(x))
   .slice(l[q]-r,l[q+1]-r)[R](/\d/g,x=>'\\/'[x^f])+n).repeat(c)+n+n
  ))+n)(0)+J([...F(1)].reverse(r-=23))+'\n'))+f[R](/./g,'¯')

```

**Code (edit 2)**

```
D=(a,b)=>{
  F=(s,f)=>(s=s[R](/\d/g,x=>'/\\'[x^f]),f?s:[...s].reverse().join('')),
  v="9.299.' *.87O2' O *3O21 O A O 1|0' 0|1 .|1|01 1|0|1|0 | .2|2*| |4| |1 01 0'.1 0*. 1 021 0|"
    [R='replace'](/\d/g,x=>x>1?' '.repeat(x):x),
  l=[0,3,6,13,19,23];
  for(o='',r=0;v[r];r+=23,f=F(z,1)+'  '+F(w,0),o+=f+'\n',f=f[R](/./g,'¯'))
    for(z=w=p='';p<10;++p)
      if(c=(p<5?a:b)[q=p%5])x=(v.slice(r+l[q],r+l[q+1])+' ').repeat(c)+'  ',p<5?z+=x:w+=x
  return o+f
}

```

**Ungolfed code (1st version)**

```
D=(a,b)=>{
  v="         .                .                    .' *.            .* '.               O  ' O *   O  / O A * O ' \\  O  A O  O /|\\' \\|/ .|/|\\/ /|\\|. \\|/ ' \\/|\\||/|\\/|\\ | .  |  *| |    | |*  |  .   | || | / \\/ \\'./ \\*. / \\  / \\|.*/ \\'.  / \\ |/ \\"
  l=[0,3,6,13,19,23,30,36,40]
  o=''
  for(r=0;r<6;++r)
  {
    z=w=''
    for(p=0;p<10;p++)
    {
      c=a[p]||b[p-5];
      if (c)
      {
        q = p<7 ? p%5 : p-2
        x = (v.slice(r*40+l[q],r*40+l[q+1])+' ').repeat(c)
        if (p<5)
          z+=x+'  ';
        else
          w=x+'  '+w
      }
    }
    f = z + '     ' + w
    o += f + '\n'
    f = '¯'.repeat(f.length-3)
  }
  return o+f
}

```
> 7 votes

# Answer
## Python ~~362~~ 353

**Edit:** Removing one for-loop and using the exec statement saved 9 bytes

```
z,x,t,j=" ",input(),str.replace,0
w=0,3,6,13,19,23
a=9*z+"."+20*z+".' *."+15*z+"o  ' o *   o  a o A o a|b' b|a .|a|ba a|b|a|b | .  |  *| |    | |a ba b'.a b*. a b  a b|"
exec"b=''\nfor c in 0,1:b+=z*8*c+t(t('   '.join([z.join([a[w[k]+j:w[k+1]+j]]*v)for k,v in enumerate(x[c])if v])[::1-2*c],'a','\/'[c<1]),'b','\/'[c])\nprint b;j+=23;"*6
print'-'*len(b)

```

**Input:**

```
[0,0,2,1,1],[1,0,2,1,2]

```

**Output:**

```
   .       .                                                   .       .
 .' *.   .' *.                                               .* '.   .* '.
 ' o *   ' o *      o  /    o A        A o  A o    \  o      * o '   * o '
' \|/ . ' \|/ .   |/|\/    /|\|        |/|\ |/|\    \/|\|   . \|/ ' . \|/ '    o
.  |  * .  |  *   | |       | |        | |  | |       | |   *  |  . *  |  .   /|\
'./ \*. './ \*.    / \     / \|        |/ \ |/ \     / \    .*/ \.' .*/ \.'   / \
---------------------------------------------------------------------------------

```
> 4 votes

# Answer
# C, 418 414 404

−10 bytes thanks to **ceilingcat**

Example input:

> stickwar.exe IVMMWWWS SWM

Example output:

```

               .       .                                                            .
             .' *.   .' *.                                                        .* '.
       O     ' O *   ' O *      O  /   O  /   O  /    O A        A O    \  O      * O '
 O    /|\   ' \|/ . ' \|/ .   |/|\/  |/|\/  |/|\/    /|\|        |/|\    \/|\|   . \|/ '
/|\    |    .  |  * .  |  *   | |    | |    | |       | |        | |       | |   *  |  .
/ \   / \   './ \*. './ \*.    / \    / \    / \     / \|        |/ \     / \    .*/ \'.
----------------------------------------------------------------------------------------

```

Golfed code:

```
char*s,d[8][999],*a;p,f,t,x,y,c,l;main(o,g)char**g;{for(memset(d,32,6993);o-=2,a=*++g;p+=3)for(;f=*a;t-4-o||strcpy(d[5]+p-1,"'."),p+=l&-o,f^*++a?p+=2:0)for(t=f%27%5,l=t*3%12%5+4,p+=l&o,y=6,s="(A(21;\0(A2:B(212;F\08A*B*0210KP\0-70A47/RT-A20G=CD?5D7_\0(A:(21;"+"V3'? "[t]-32;c=*s++;d[y][p+o*x]="/\\|O*'A."[c&7])x=c/16-2+(c&8?--y*0:x),c^=o-1&&!(c&6);for(y=!memset(d[6],45,p-=4);*(s=d[y++]);s[p]=0,puts(s));}

```

Maximal width of the battlefield is 999 (I could save 2 chars by limiting it to 99). I used a control structure of 1 byte per output character (non-space), drawing the figures from the bottom up.

* 1 bit for y-coordinate (either "stay" or "go up")
* 3 bits for x-coordinate displacement (0...4)
* 3 bits for output char (fortunately, there are only 8 different chars)

There are 5 offsets into the control structure.

Some other obscure bits:

* The code `f%27%5` translates the characters `VWSMI` to numbers `0, 1, 2, 3, 4`
* The code `t*3%12%5+4` calculates the width of the stickman of type `t`
* The code `t^3|~o||(s=d[5]+p,*s--=46,*s=39)` accounts for the left/right asymmetry
* I use the fact that `argc=3` to generate drawing direction flags `1` and `-1`

Ungolfed code:

```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char k[] = "(A(21;\0(A2:B(212;F\08A*B*0210KP\0-70A47/RT-A20G=CD?5D7_\0(A:(21;";

char d[8][999], // data of the battlefield
*s, // control string
*a; // cmdline argument
p, // position in the battlefield
f, // figure (char)
t, // type of the figure (0...4)
x,y, // coordinates while drawing the stickman
c; // control char, specifying what to draw

main(o, g) char**g; // o means "orientation" (+1, then -1)
{
    freopen("out.txt", "w", stdout);
    memset(d, ' ', 6993);

    for (; o -= 2, a=*++g;)
    {
        for (; f=*a;)
        {
            t = f%27%5;

            if (o<0)
                p += t*3%12%5+4; // go to the next stickman

            y = 6;
            for (s=k+"V3'? "[t]-32; c = *s++;) // loop over the control
            {
                if (c & 8) // bit 3: next line; set x to 0
                    --y, x = 0;
                x += c / 16 - 2; // bits 6...4: x coordinate
                if (o == -1 && !(c & 6)) // mirror \ <-> /
                    c ^= 1;
                d[y][p + o * x] = "/\\|O*'A."[c & 7];
            }
            if (t == 3 && o<0) // fix the asymmetrical mage
            {
                s=d[5]+p;
                *s--='.';
                *s='\'';
            }

            if (o>0)
                p += t*3%12%5+4; // go to the next stickman
            if (f != *++a) // is next stickman of different type?
                p += 2;
        }
        p += 3; // separate the armies
    }

    p -= 4;
    memset(d[6], '-', p); // draw the ground

    for (y = 0; *(s=d[y++]); ) // print the battle field
    {
        s[p] = 0;
        puts(s);
    }
}

```
> 3 votes

# Answer
## Haskell, 556

### Input Format

```
([1,1,2,3,1],[0,1,1,0,1])

```

Order: \[Infant, Villager, Mage, Swordsman, Spearman\], \[Spearman, Swordsman, Mage, Villager, Infant\]

### Sample Output

```
               .        .                                                       .
             .' *.    .' *.                                                   .* '.
       O     ' O *    ' O *       O  /   O  /   O  /    O A        \  O       * O '
 O    /|\   ' \|/ .  ' \|/ .    |/|\/  |/|\/  |/|\/    /|\|         \/|\|    . \|/ '    O
/|\    |    .  |  *  .  |  *    | |    | |    | |       | |           | |    *  |  .   /|\
/ \   / \   './ \*.  './ \*.     / \    / \    / \     / \|          / \     .*/ \.'   / \
------------------------------------------------------------------------------------------

```

### Code

```
(?)=replicate
v=reverse
g=map
e=length
s=foldr1
p=zip[3,3,8,6,4]$g lines[" O\n/|\\\n/ \\"," O\n/|\\\n |\n/ \\","   . \n .' *.\n ' O *  \n' \\|/ .\n.  |  *\n'./ \\*.","  O  /\n|/|\\/\n| |\n / \\"," O A\n/|\\|\n | |\n/ \\|"]
r n x a=a++(n-e a)?x
x '\\'='/';x '/'='\\';x c=c
y(w,p)=(w,g(v.dropWhile(==' ').g x.r w ' ')p)
m n(a,p)(b,q)=(a+b+n,[r(a+n)' ' c++d|(c,d)<-zip(h p)(h q)])where h=v.r(max(e p)(e q))[].v
p%c|sum c==0=(0,[])|1<2=s(m 3)[s(m 1)$d?(p!!i)|(i,d)<-zip[0..]c,d>0]
f(w,p)=p++[w?'-']
main=interact((\(a,b)->unlines.f$m 8(p%a)((g y.v$p)%b)).read)

```

### Ungolfed

```
type Pic = (Int, [String])

pics :: [Pic]
pics = zip[3,3,8,6,4]$map lines[" O\n/|\\\n/ \\"," O\n/|\\\n |\n/ \\","   . \n .' *.\n ' O *  \n' \\|/ .\n.  |  *\n'./ \\*.","  O  /\n|/|\\/\n| |\n / \\"," O A\n/|\\|\n | |\n/ \\|"]

mirrorChar '\\' = '/'
mirrorChar '/' = '\\'
mirrorChar c = c

padL, padR :: Int -> a -> [a] -> [a]
padL n x a = replicate (n - length a) x ++ a
padR n x a = a ++ replicate (n - length a) x

mirrorPic :: Pic -> Pic
mirrorPic (w, pic) = (w, map (reverse . dropWhile (==' ') . map mirrorChar . padR w ' ') pic)

merge n (w1, pic1) (w2, pic2) =
  let h = max (length pic1) (length pic2)
  in (w1 + n + w2, [padR (w1 + n) ' ' line1 ++ line2 | (line1, line2) <- zip (padL h [] pic1) (padL h [] pic2)])

makeArmy :: [Pic] -> [Int] -> Pic
makeArmy pics counts | sum counts == 0 = (0, []) | otherwise = foldr1 (merge 3) [ foldr1 (merge 1) . replicate count $ pics !! i | (i, count) <- zip [0..] counts, count > 0]

addField :: Pic -> [String]
addField (w, pic) = pic ++ [replicate w '-']

main = do
  (counts1, counts2)<- return . read =<< getLine
  putStr . unlines . addField $ merge 8 (makeArmy pics counts1) (makeArmy (map mirrorPic . reverse $ pics) counts2)

```
> 2 votes

# Answer
# Haskell (~~736~~ ~~733~~ 720 Bytes)

```
import System.Environment
import Data.List
a=1<2
h="   "
n="      "
o="    "
b (x:y)|x<0=[]|a=x:(b y)
c (x:y)|x>=0=c y|a=y
d [] _=[]
d (x:y)z|z/=x=[-5,x]++(d y x)|a=[x]++(d y x)
e x y|x< -5="        "|x<0=h|a=(([[h,h,"   .   ",n,o],[h,h," .' *. ",n,o],[h," o "," ' O * ","  O  /"," O A"],[" o ","/|\\", "' \\|/ .","|/|\\/ ","/|\\|"],["/|\\"," | ",".  |  *","| |   "," | |"],["/ \\","/ \\","'./ \\*."," / \\  ","/ \\|"]]!!(div z 5))!!(mod z 5))++" "where z=5*y+x
(§)=map
g=putStrLn
m=concat
main=do
    z<-getArgs
    let y=read§z::[Int]
    let w=sort(b y)
    let v=reverse(sort(c y))
    let u=(\(t,i)->(\s->e s i)§t)§(zip(take 6(cycle[((d w (w!!0))++[-9]++(d v (v!!0)))]))[0..5])
    mapM(\x->g(m x))u
    g(replicate(length(m(u!!0)))'-')

```

Call with **./stickmanwars 2 3 1 3 4 -1 3 2 4 1 0 4 2 1**. The -1 marks the delimiter for the two arrays. I hope that is okay.

Well, my first code golf challenge and the first time I've used haskell for a real application after I learned it this semester at my university. Probably not even close to being the best or shortest solution but I had fun creating it and it was a good exercise :) Critique and feedback is highly appreciated.

Golfed it out of this:

```
import System.Environment
import Data.List

layers = [
    ["   ", "   ",  "   .   ",  "      ",  "    "],
    ["   ", "   ",  " .' *. ",  "      ",  "    "],
    ["   ", " o ",  " ' O * ",  "  O  /",  " O A"],
    [" o ", "/|\\", "' \\|/ .", "|/|\\/ ", "/|\\|"],
    ["/|\\"," | ",  ".  |  *",  "| |   "," | |"],
    ["/ \\","/ \\", "'./ \\*.", " / \\  ","/ \\|"],
    ["¯¯¯", "¯¯¯",  "¯¯¯¯¯¯¯",  "¯¯¯¯¯¯", "¯¯¯¯"]]

getLeftSide :: [Int] -> [Int]
getLeftSide (x:xs) | x < 0 = []
                   | otherwise = x : (getLeftSide xs)

getRightSide :: [Int] -> [Int]
getRightSide (x:xs) | x >= 0 = getRightSide xs
                    | otherwise = xs

addSpacing :: [Int] -> Int -> [Int]
addSpacing [] _ = []
addSpacing (x:xs) old | old /= x = [(-50),x] ++ (addSpacing xs x)
                      | otherwise = [x] ++ (addSpacing xs x)

getLayerStr :: Int -> Int -> String
getLayerStr item dimension | item < (-50) = "        "
getLayerStr item dimension | item < 0  = "   "
                           | otherwise = ((layers !! i) !! j) ++ " "
    where
        value = (item + (5 * dimension))
        i = div value 5
        j = mod value 5

main = do
    -- Read Arguments from command line
    a <- getArgs
    -- Convert command line arguments to Int array
    let args = map read a :: [Int]
    -- Get left side of the array and sort it
    let frstArray = sort $ getLeftSide args
    -- Get right side of the array and sort it mirrored
    let scndArray = reverse $ sort $ getRightSide args
    -- Concat the two sides and put a delimiter in between them
    let finalArray = (addSpacing frstArray (frstArray !! 0)) ++ [-99] ++ (addSpacing scndArray (scndArray !! 0))
    -- Create the matrix by
    -- 1. Duplicating the final array 6 times (one for each level)
    -- 2. Pair each of those 6 arrays with its level (= index)
    -- 3. Create a matrix like below:
    --
    -- 1  1  2  2  3  4  4  5 -  1  1  2  2  2  4
    -- 6  6  7  7  8  9  9 10 -  6  6  7  7  7  9
    -- 11 11 12 12 13 14 14 15 - 11 11 12 12 12 14
    -- 16 16 17 17 18 19 19 20 - 16 16 17 17 17 19
    -- 21 21 22 22 23 24 24 25 - 21 21 22 22 22 24
    -- 26 26 27 27 28 29 29 20 - 26 26 27 27 27 29
    --
    -- 4. Convert the newly calculated indices to their respective strings
    let matrix = map (\(list,i) -> map (\item -> getLayerStr item i) list) (zip (take 6 $ cycle [finalArray]) [0..5])
    -- Finaly output the matrix by concating the elements ...
    mapM (\x -> putStrLn (concat x)) matrix
    -- ... and print the ground level.
    putStrLn (replicate (length $ concat $ matrix !! 0) '¯')
    -- Exit with a new line
    putStrLn ""

```
> 1 votes

# Answer
# 05AB1E, 120 bytes

```
εU•1ĆÊLî˜₅ÉÈ«-—gí"Mª§ÚÇGäÒ²ĀÛNYE™Eæ]Ç€Š–ôTú™<C₄+i*∍.[½P•"
|/\.O*'0A"ÅвJ0¡ε.B€S¸XNèиJøðý€S}õζJð3×ýNiεº2äθðÜ]øð8×ý¤'-s∍ª»

```

Input is similar as in the example, except it's paired together (i.e. `[[1,1,2,3,1],[0,0,1,1,1]]`).

Try it online.

**Explanation:**

```
ε                 # Map both inner lists of the (implicit) input to:
 U                #  Pop and store the list in variable `X`
  •1ĆÊLî˜₅ÉÈ«-—gí"Mª§ÚÇGäÒ²ĀÛNYE™Eæ]Ç€Š–ôTú™<C₄+i*∍.[½P•
                 "#  Push compressed integer 842496640498468305486897242730433696271358810529289612091214532817389449608887173562606281130145674459118763657187307135640
"
|/\.O*'0A"        #  Push string " \n|/\.O*'0A"
          Åв      #  Convert the integer to this custom base-" \n|/\.O*'0A",
                  #  (short for converting it to base-length and indexing each into the string)
            J     #  Join this list of characters together to a single string
             0¡   #  And split it on "0"s

```

We now have a list of stick figures. I've generated the stick figures string with this program, which is a slightly modified version of this 05AB1E tip.

```
 ε                #  Map each stick figure to:
  .B              #   Box it (split on newlines, and append spaces to make all lines of equal length)
    €S            #   Convert each line to a list of characters
      ¸           #   Wrap the entire thing into a list
       X          #   Push input-sublist `X`
        Nè        #   Index the map-index into it
          и       #   Repeat the stick figure that many times as list
           J      #   Join each innermost list of characters together to a string
            ø     #   Zip/transpose; swapping rows/columns
             ðý   #   Join each line with a single space delimiter
               €S #   And convert each line back to a character list again
 }                #  After the inner map:
   ζ              #  Zip/transpose the list of stick figures,
  õ               #  with an empty string as filler (in case the input contained a 0)
    J             #  Join each inner list together to a string
     ð3×ý         #  Join each line with 3 spaces as delimiter
 Ni               #  If the map-index is 1 (thus the left army):
   ε              #   Map each line to:
    º             #    Mirror-reflect the line
     2ä           #    Split it into 2 equal-sized parts
       θ          #    Pop and only leave the last (mirrored) part
        ðÜ        #    Remove any trailing spaces
                  #    (necessary if the amount of infants in the left army is 0)
]                 # Close all maps and if-statements
 ø                # Zip/transpose; swapping rows/columns
  ð8×ý            # Join each line together with 8 spaces as delimiter
      ¤           # Push the last line (without popping the list itself)
       '-        '# Push string "-"
         s        # Swap so the last line is at the top of the stack
          ∍       # Extend the "-" to a length equal to that line
           ª      # Append it to the list
            »     # And join the lines by newlines
                  # (after which the result is output implicitly)

```

See this 05AB1E tip of mine (section *How to compress large integers?*) to understand why `•1ĆÊLî˜₅ÉÈ«-—gí"Mª§ÚÇGäÒ²ĀÛNYE™Eæ]Ç€Š–ôTú™<C₄+i*∍.[½P•` is `842496640498468305486897242730433696271358810529289612091214532817389449608887173562606281130145674459118763657187307135640`.
> 1 votes

# Answer
# Python (~~612~~,~~522~~,~~460~~,440)

* Rev1: Rudimentary compression and base64-encoding
* Rev2: Removed compression/encoding; got smaller
* Rev3: More byte count reduction by inlining
* Rev4: Removed unneeded input reversal on 2nd army; swapped swordsman and spearman to match spec

Each "line" is trimmed of right-padding, and this is added back in when reconstructing.

I pre-reversed the stickmen in my internal encoding because it saved me having to reverse them individually when rendering them in the code.

Sample run:

```
$ echo "[1,1,2,3,1],[0,0,1,1,1]"|python /tmp/g2.py
               .       .                                                            .
             .' *.   .' *.                                                        .* '.
       O     ' O *   ' O *      O  /   O  /   O  /    O A        A O    \  O      * O '
 O    /|\   ' \|/ . ' \|/ .   |/|\/  |/|\/  |/|\/    /|\|        |/|\    \/|\|   . \|/ '
/|\    |    .  |  * .  |  *   | |    | |    | |       | |        | |       | |   *  |  .
/ \   / \   './ \*. './ \*.    / \    / \    / \     / \|        |/ \     / \    .*/ \.'
----------------------------------------------------------------------------------------

```

Code:

```
c=",,A O,|/|\\,| |,|/ \\,,,\\  O, \\/|\\|,   | |,  / \\,   .  , .* '., * O ',. \\|/ ',*  |  .,.*/ \\.',,, O,/|\\, |,/ \\,,,, O,/|\\,/ \\".split(',')
r=['']*6
for b in input():
    for e,f in '/$ \\/ $\\'.split():r=[x.replace(e,f)[::-1] for x in r]
    if r[0]:r=[x+'  ' for x in r]
    for n,a in enumerate(b[::-1]):
        m=c[n*6:n*6+6]
        if a:r=[x+'   '+(' '.join([y.ljust(max(map(len,m)))]*a)) for x,y in zip(r,m)]
print '\n'.join(r+['-'*len(r[0])])

```
> 0 votes

# Answer
# Haskell, 450

```
import Data.List
s=["      -"]
c=["    //-":"   O| -":"    \\\\-":s,"   / /-":"  O|| -":"   \\ \\-":s,"   '.'-":" .'  .-":" ' \\ /-":". O|| -":" * / \\-":" .*  *-":"   .*.-":s,"   || -":"   / /-":"  O|| -":"   \\ \\-":"   /  -":"  /   -":s,"   / /-":"  O|| -":"   \\ \\-":"  A|||-":s]
m '\\'='/'
m '/'='\\'
m x=x
u[]=[]
u x=x++[s,s]
f x=zipWith replicate x c>>=concat.u
k(a,b)=unlines.transpose$f a++s++s++map(map$m)(reverse$f b)
main=interact$k.read

```

Cool challenge! I might be able to golf that down a bit more. Basically I'm storing the figures column wise so I can append them to each other easily, and then flip the whole array of `String`s arround using Haskell's `transpose`.

The input format is `([Infants,Villagers,Mages,Swordsmen,Spearmen],[Infants,Villagers,Mages,Swordsmen,Spearmen])`

Here is the example from the OP:

```
>>>echo ([1,1,2,3,1],[0,0,1,1,1]) | cg2
               .       .                                                            .
             .' *.   .' *.                                                        .* '.
       O     ' O *   ' O *      O  /   O  /   O  /    O A        A O    \  O      * O '
 O    /|\   ' \|/ . ' \|/ .   |/|\/  |/|\/  |/|\/    /|\|        |/|\    \/|\|   . \|/ '
/|\    |    .  |  * .  |  *   | |    | |    | |       | |        | |       | |   *  |  .
/ \   / \   './ \*. './ \*.    / \    / \    / \     / \|        |/ \     / \    .*/ \.'
----------------------------------------------------------------------------------------

```

And here is my favourite depiction of the infamous ritual infanticide during the second era!

```
>>>echo ([0,0,0,1,0],[5,0,0,0,0]) | cg2

  O  /
|/|\/          O   O   O   O   O
| |           /|\ /|\ /|\ /|\ /|\
 / \          / \ / \ / \ / \ / \
---------------------------------

```
> 0 votes

# Answer
# Python (476)

A different solver from my previous one; longer, but more functional.

```
$ echo "[1,1,2,3,1],[0,0,1,1,1]"|python g3.py
               .       .                                                            .
             .' *.   .' *.                                                        .* '.
       O     ' O *   ' O *      O  /   O  /   O  /    O A        A O    \  O      * O '
 O    /|\   ' \|/ . ' \|/ .   |/|\/  |/|\/  |/|\/    /|\|        |/|\    \/|\|   . \|/ '
/|\    |    .  |  * .  |  *   | |    | |    | |       | |        | |       | |   *  |  .
/ \   / \   './ \*. './ \*.    / \    / \    / \     / \|        |/ \     / \    .*/ \.'
----------------------------------------------------------------------------------------

```

Code:

```
c=",,A O,|L|R,| |,|L R,,,R  O, RL|R|,   | |,  L R,   .  , .* '., * O ',. R|L ',*  |  .,.*L R.',,, O,L|R, |,L R,,,, O,L|R,L R".split(',')+['']*12
s=[sum([[4-n,5]*a+[6] for n,a in enumerate(b) if a]+[[5]],[])[::-1] for b in input()]
t=[[''.join([c[a*6+n].ljust([4,6,7,3,3,1,2][a]) for a in x]) for x in s] for n in range(0,6)]
for d,e,f in 'RL/ LR\\'.split():t=[[x[0].replace(d,f),x[1].replace(e,f)] for x in t]
t=[x[0][::-1]+x[1] for x in t]
print '\n'.join(t+['-'*len(t[0])])

```
> 0 votes

---
Tags: code-golf, ascii-art, kolmogorov-complexity
---


# Question
Title: Checking a Windows 95 OEM Key for validity
### Introduction

Windows 95 used a very simple algorithm for verifying license keys. The scheme of an OEM license key always looked like this:

```
xxxyy-OEM-NNNNNNN-zzzzz

```

The day can be anything within 001-366, and the year cannot be lower than 95 or above 03.

`xxx` represents the day of the year the key was printed on (for example 192 = 10th of July) and is a number between 001-366. `yy` represents the year the key was printed on and cannot be lower than 95 or above 03.

This means for example, a key with 19296 as the first segment was printed on 10th of July 1996.

The second segment is always OEM.

The third segment (NN..) is always starts with `00` and the sum of the digits has to be divisible by 7

The fourth segment is irrelevant, provided the field is the appropriate length, but has to be filled out with digits.

### Challange

Given a string, output a truthy or falsy value whether this oem key is valid or not.

### Rules

* You may provide a function or a program
* This is , so the submission with the least amount of bytes wins!

### Test cases

## Valid keys

```
12899-OEM-0042134-31009
15795-OEM-0001355-07757
35201-OEM-0009165-64718

```

## Invalid keys

```
12804-OEM-0033143-31009
16595-OEM-0001695-9
12899-OEM-0022134-31009
27497-OEM-0525347-80387

```

# Answer
> 2 votes
# perl -pl -MList::Util=sum, 106 113 bytes

```
$_=/^(?!000)(([012]\d\d|3([0-5]\d|6[0-5]))(9[5-9]|0[0-3])|366(00|96))-OEM-00(\d{5})-\d{5}$/&&!(sum(split//,$6)%7)

```

Try it online!

This assumes an ASCII only input. If the input can be outside of ASCII, we'd have to add a single extra byte (a trailing `a` modifier on the main regexp). It also assumes a leading `366` can only occur in the years `96` and `00`, them being leap years. The bulk of the matching is done by a regexp; testing of divisibility by 7 is done outside of it.

Reads keys from `STDIN`; writes `1` to `STDOUT` for valid keys, empty lines for invalid keys.

Edit: fixed the issue mentioned by @Dingus.

# Answer
> 1 votes
# Ruby -n, 110 bytes

```
p~/^(\d{3})(9[5-9]|0[0-3])-OEM-(00\d{5})-\d{5}$/&&$3.to_i.digits.sum%7<1&&$1>?0*3&&$1<"36#{$2=~/6|0$/?7:6}"||p

```

Try it online!

Takes input on STDIN. Outputs `true` to STDOUT for valid keys and `nil` for invalid keys.

Uses three regex capture groups: `$1` is `xxx`, `$2` is `yy`, and `$3` is `NNNNNNN`. First tests whether the key has the correct general format. If so, then tests whether the sum of digits in `$3` is divisible by 7. Then tests whether `$1` is lexicographically greater than `'000'` and less than either `'366'` (non-leap years) or `'367'` (leap years); this works because we know at this point that `$1` is a string of three digits. Leap years occur when `$2` contains `6` or ends with `0`.

# Answer
> 1 votes
# 05AB1E, ~~73~~ ~~85~~ 78 bytes

```
•J" L•S£ε"©366L ₃Ƶ2Ÿт%y4Ö≠i®366Ê* '- …OEM '- 0мõ ÐþQ×SO7Ö1 '- ÐþQ×g5"#Nè.VQà}P

```

+12 bytes to account for leap years.

Will try to golf it down from here. If only 05AB1E had regex.. :/

Try it online or verify a lot more test cases.

**Explanation:**

```
•J" L•      "# Push compressed integer 321312516
      S      # Convert it to a list of digits: [3,2,1,3,1,2,5,1,6]
       £     # Split the (implicit) input-string into parts of that size
ε            # Map each part to:
 "©366L ₃Ƶ2Ÿт%y4Ö≠i®366Ê* '- …OEM '- 0мõ ÐþQ×SO7Ö1 '- ÐþQ×g5"
             #  Push this string
  #          #  Split the string on spaces
   Nè        #  Use the map-index to index into this string
     .V      #  Evaluate/execute it as 05AB1E code
       Q     #  Check that the top two values on the stack are equal
        à    #  Pop and take its maximum (no op if it's already a single 0/1 boolean)
}P           # After the map: check if all were truthy by taking the product
             # (after which the result is output implicitly)

```

As for each individual part:

```
             # xxx:
©            #  Store the string in variable `®` (without popping)
 366L        #  Push a list in the range [1,366]
             #  After the eval:
     Q       #   Check for each value whether it's equal to the current `xxx` part
      à      #   Check if any are truthy in this list by taking the maximum

             # yy:
₃            #  Push builtin 95
 Ƶ2          #  Push compressed integer 103
   Ÿ         #  Pop both an push a list in the range [95,103]
    т%       #  Take modulo-100 on each value
y            #  Push the current `yy` part again
 4Ö≠i        #  If it's NOT divisible by 4 (so neither 96 nor 00):
     ®       #   Push the `xxx` part from variable `®`
      366Ê   #   Check that it's NOT equal to 366
          *  #   And check if both are truthy by multiplying them together
    }        #  (implicit due to the eval: close the if-statement)
             #  After the eval:
     Q       #  Check for each value whether it's equal to the current `yy` part
      à      #  Check if any are truthy in this list by taking the maximum

             # OEM:
…OEM         #  Push string "OEM"
             #  After the eval:
    Q        #   Check if it's equal to the current `OEM` part
     à       #   No-op maximum, since the max digit of 0/1 is 0/1 respectively

             # 00:
0м           #  Remove all 0s from the current `00` part
  õ          #  Push an empty string ""
             #  After the eval:
   Q         #   Check if the `00` part with zeroes is equal to the empty string
    à        #   No-op maximum, since the max digit of 0/1 is 0/1 respectively

             # NNNNN:
Ð            #  Triplicate the current `NNNNN` part
 þ           #  Pop and only leave its digits
  Q          #  Check that it's equal to the `NNNNN` part (1 if truthy; 0 if falsey)
   ×         #  Repeat the part that many times (`NNNNN` if truthy; "" if falsey)
    S        #  Convert it to a list of characters
     O       #  Sum those digits together
      7Ö     #  Check that it's divisible by 7
        1    #  Push a 1
             #  After the eval:
         Q   #   Check whether the divisibility check is equal to the 1
          à  #   No-op maximum, since the max digit of 0/1 is 0/1 respectively

             # zzzzz:
ÐþQ×         #  Similar as above for NNNNN
    g        #  Pop and push its length
     5       #  Push a 5
             #  After the eval:
      Q      #   Check if the length is equal to the 5
       à     #   No-op maximum, since the max digit of 0/1 is 0/1  respectively

             # -:
'-          '#  Push a "-"
             #  After the eval:
  Q          #   Check if the `-` part is equal to the "-"
   à         #   No-op maximum, since the max digit of 0/1 is 0/1  respectively

```

See this 05AB1E tip of mine (section *How to compress large integers?*) to understand why `•J" L•` is `321312516` and `Ƶ2` is `103`.

---
Tags: code-golf, string, number
---


title: Determine the Sharpness of a Word

text:
# Question
Title: Determine the Sharpness of a Word
## Overview

The *sharpness* of a word is the sum of the sharpness of each of its letters, using the following rules:

**Sharp letters**

* `A`, and `V` each have a sharpness of **1**
* `N` and `Z` each have a sharpness of **2**
* `M` and `W` each have a sharpness of **3**

**Dull letters**

* `C` and `U` each have a sharpness of **-1**
* `S` has a sharpness of **-2**
* `O` has a sharpness of **-3**

**All other letters** have a sharpness of **0**.

### Example

The word `SAUCE` has a sharpness of **-3** since the `A` contributes 1, the `U` and `C` each contribute -1 and the `S` contributes -2.

The word `MAZE` has a sharpness of **6** since the `M` contributes 3, the `Z` contributes 2, and the `A` contributes 1.

## Task

Given as input a string containing only uppercase letters\*, determine the sharpness of that string.

\*If you wish, you may instead take the input as a string containing only lowercase letters. Other common input formats are also acceptable (eg. a list of characters, a list of codepoints, etc.)

## Scoring

This is !

## Test Cases

```
CODE => -4
GOLF => -3
SAUCE => -3
CATS => -2
MOON => -1
NONSENSE => -1
ZUCKERBERG => 0
STRING => 0
CHALLENGE => 2
NAIL => 3
CARNIVAL => 4
COMPLIMENT => 4
WAVE => 5
UNKNOWN => 5
MAZE => 6

```

**Extra test cases (Provided by @Surculose Sputum)**

```
MIZZENMASTMAN => 17
PNEUMONOULTRAMICROSCOPICSILICOVOLCANOCONIOSIS => -26
MANAGEMENT => 12
CONSCIOUSNESS => -13

```

# Answer
> 13 votes
# Python 2, 53 bytes

```
lambda s:sum(3-"MWCUNZS_AVO".find(c)/2*4%7for c in s)

```

Try it online!

# Answer
> 9 votes
# Jelly, 21 bytes

```
“CSO“ANM“U“VZX”iⱮ€§ḅ-

```

A monadic Link accepting a list of characters which yields an integer.

**Try it online!**

### How?

```
“CSO“ANM“U“VZX”iⱮ€§ḅ- - Link: list of characters, W
“CSO“ANM“U“VZX”       - list of lists of characters = [['C','S','O'],['A','N','M'],['U'],['V','Z','X']]
                 €    - for each (L in those four lists):
                Ɱ     -   map across (c in W) with:
               i      -     first (1-based) index (of c in L) or 0 if not found
                  §   - sum each resulting list
                    - - literal minus one
                   ḅ  - convert (the list of four sums) from base (-1)

```

# Answer
> 9 votes
# JavaScript (Node.js),  ~~61~~  53 bytes

A lookup table based on the ASCII code of each letter.

Takes input as a list of codepoints.

```
a=>a.map(c=>t+='50363133463254'[(c^98)%22]-3|0,t=0)|t

```

Try it online!

### How?

By XOR'ing the ASCII code with **98** and applying a modulo **22**, we gather the characters with a non-zero sharpness into the range **\[0..13\]**. This results in a lookup table of **14** entries.

If the result of the formula is out of range, we get `undefined - 3 | 0`, which is **0**.

```
 char. | code | XOR 98 | MOD 22 | sharpness
-------+------+--------+--------+-----------
  'A'  |  65  |   35   |   13   |    +1
  'B'  |  66  |   32   |   10   |
  'C'  |  67  |   33   |   11   |    -1
  'D'  |  68  |   38   |   16   |
  'E'  |  69  |   39   |   17   |
  'F'  |  70  |   36   |   14   |
  'G'  |  71  |   37   |   15   |
  'H'  |  72  |   42   |   20   |
  'I'  |  73  |   43   |   21   |
  'J'  |  74  |   40   |   18   |
  'K'  |  75  |   41   |   19   |
  'L'  |  76  |   46   |    2   |
  'M'  |  77  |   47   |    3   |    +3
  'N'  |  78  |   44   |    0   |    +2
  'O'  |  79  |   45   |    1   |    -3
  'P'  |  80  |   50   |    6   |
  'Q'  |  81  |   51   |    7   |
  'R'  |  82  |   48   |    4   |
  'S'  |  83  |   49   |    5   |    -2
  'T'  |  84  |   54   |   10   |
  'U'  |  85  |   55   |   11   |    -1
  'V'  |  86  |   52   |    8   |    +1
  'W'  |  87  |   53   |    9   |    +3
  'X'  |  88  |   58   |   14   |
  'Y'  |  89  |   59   |   15   |
  'Z'  |  90  |   56   |   12   |    +2

```

# Answer
> 9 votes
# Python 2, 52 bytes

```
lambda s:sum(3-"MCNSAO_WUZ_V".find(c)*4%7for c in s)

```

Try it online!

Improvement on @xnor's answer.

```
M C N S A O _ W U Z _ V ?  c
0 1 2 3 4 5 6 0 1 2 3 4 6  "...".find mod 7
0 4 1 5 2 6 3 0 4 1 5 2 3  "...".find*4 mod 7
3-1 2-2 1-3 0 3-1 2-2 1 0  (3-"...".find*4 mod 7)

```

\*4 is to map -1 (failed find) onto 0

# Answer
> 5 votes
# APL+WIN, ~~42~~ 38 bytes.

Prompts for string:

```
   +/(2/¯3+⍎¨'4562103')['AVNZMWCUS O '⍳⎕]

```

Try it online! Courtesy of Dyalog Classic

Explanation:

```
⍎¨'4562103' Split number as a string into individual digits and convert to integers

2/¯3+ Subtract 3 to give the non-zero letter values and double up each value

['AVNZMWCUS O '⍳⎕] Find the index position of non-zero letters that occur in the input.
If a letter is not in list it is given an index of length of list + 1

+/ Sum the values corresponding to the indices of non-zero letters in string

```

# Answer
> 5 votes
# C(GCC) ~~84~~ ~~73~~ 72 bytes

*-11 bytes thanks to ceilingcat*

```
t;f(char*s){for(t=0;*s;t+=""[*s++-65]-4);s=t;}

```

(note that StackExchange strips some non-printing characters)

Try it online!

# Answer
> 5 votes
# APL (Dyalog Unicode), 31 bytes

```
-/1⊥¨4|(↓4 3⍴'ANMCSOVZWU  ')⍳¨⊂

```

Try it online!

Tacit function.

### How it works

```
-/1⊥¨4|(↓4 3⍴'ANMCSOVZWU  ')⍳¨⊂  ⍝ Input: string S
       (↓4 3⍴'ANMCSOVZWU  ')     ⍝ 'ANM' 'CSO' 'VZW' 'U  '
                            ⍳¨⊂  ⍝ Find the index of each char in S in each of above
                                 ⍝ Index is 1-based, not found gives 4
     4|  ⍝ Modulo 4; convert 4 to 0
  1⊥¨    ⍝ Sum of each row
-/       ⍝ Alternating sum; (ANM score)-(CSO score)+(VZW score)-(U score)

```

# Answer
> 4 votes
# Python 2, ~~62~~ 60 bytes

-2 bytes thanks to @Neil!

```
lambda w:sum('AVNZMW'.find(c)/2-'CUS_O'.find(c)/2for c in w)

```

Try it online!

# Answer
> 3 votes
# Python 3, 61 bytes

Input is taken as a byte-string \\$ s \\$.

```
lambda s:sum(b''[c-65]-4for c in s)

```

Try it online!

We use a lookup table, where each element maps to the *sharpness* of a given letter. Note the `-4`, to display the negative *sharpness*.

# Answer
> 3 votes
# Retina 0.8.2, ~~61~~ 60 bytes

```
M|W
N#
N|Z
##
O
S-
S
--
T`VAUC`##-
+`\w|-#|#-

^(-)?.*
$1$.&

```

Try it online! Link includes test cases. Edit: Saved 1 byte thanks to @mathjunkie. Explanation:

```
M|W
N#
N|Z
##
O
S-
S
--
T`VAUC`##-

```

Turn sharp letters into the appropriate number of `#` (sharp... geddit? any non-word non-magic non-`-` character would have worked) signs and dull letters into the appropriate number of `-` (because they have negative sharpness) signs.

```
+`\w|-#|#-

```

Delete other letters and all matching pairs of `#` and `-` signs.

```
^(-)?.*
$1$.&

```

Output the number of signs remaining, prefixed by the first one if it's a `-`. Since the regex matches a zero-length string, I have to ensure it only matches once.

# Answer
> 3 votes
# Javascript (Babel Node), 131 bytes

```
d=>(s=0,[...d].map(c=>{s+=/[AV]/.test(c)?1:(/[NZ]/.test(c)?2:(/[MW]/.test(c)?3:(/[CU]/.test(c)?-1:(c=='S'?-2:(c=='O'?-3:0)))))}),s)

```

Try it online!

This is my first code golfing. I hope I'm doing it right.

I'll be glad to get some js golfing tips (before exploring new golfing languages) and overall golfing tips.

# Answer
> 3 votes
# Javascript (Node.js), 115 bytes

```
let s=0;for(let b='w'+w,c=a=>Math.ceil(10*3**(4/~'OSCUAVNZMW'.indexOf(a[0])))-4||-1;b=b.slice(1);s+=9>c(b)?c(b):0);

```

Try it online!

This puts all the characters in a string, 'OSCUAVNZMW', and uses a formula to map the character index to the "sharpness" of each letter. The formula is:

\\$f\left(x\right)=ceil\left(10\cdot3^{\frac{4}{x}}-4\right)\\$

Where \\$f(x)\\$ is the sharpness, and \\$x\\$ is the negative index of the character + 1. Sounds convoluted, but there's a reason: the index is modified to make Javascript's `string.indexOf()` return 0 instead of -1.

This formula does result in 0 instead of -1 for U. However, using Javascript's `||` functionality in variable assignment, we can just default zero values to -1 instead.

Also, this is my first code golf, advice appreciated!

# Answer
> 3 votes
## Javascript (ES6), 65 characters

```
x=>x.map(l=>s-=~(z='RosLucyEvanzmw'.indexOf(l))?~(z/2)+4:0,s=0)|s

```

## Javascript (ES6), 67 characters

```
x=>x.reduce((s,l)=>~(z='RosLucyEvanzmw'.indexOf(l))?s-~(z/2)-4:s,0)

```

Takes an array of lowercase characters as input.

# Answer
> 3 votes
# Java (JDK), 56 bytes

```
s->s.map(c->("XXAVNZMWOOSSCU".indexOf(c)/2+3)%7-3).sum()

```

Try it online!

# Answer
> 2 votes
# Stax, ~~20~~ 19 bytes

```
ô≈X╙R┤╠Φyf∙H¡»₧ßc≡╡

```

Run and debug it

# Answer
> 2 votes
# Charcoal, ~~25~~ 24 bytes

```
ＩΣＥＳ⁻÷⌕AVNZMWι²÷⌕UCSSOι²

```

Try it online! Link is to verbose version of code. Edit: Saved 1 byte by porting @ovs' answer. Explanation:

```
   Ｓ                        Input string
  Ｅ                         Map over characters
             ι              Current character
      ⌕                     Find position in
       AVNZMW               Literal string `AVNZMW`
     ÷        ²             Integer divide by literal `2`
    ⁻                       Minus
                      ι     Current character
                ⌕           Find position in
                 UCSSO      Literal string `UCSSO`
               ÷       ²    Integer divide by literal `2`
 Σ                          Take the sum
Ｉ                           Cast to string
                            Implicitly print

```

The halved `Find` results in one less than the sharpness/dullness, but the other find returns `-1` in that case, thus correcting the value.

# Answer
> 2 votes
# Keg, 42 bytes

```
?⑷¦A1|V1|N2|Z2|M3|W3|C1±|U1±|S2±|O3±║_0™⑸⅀

```

Unfortunately, TIO doesn't have the latest version of the interpreter on its servers, so y'all can't try it online.

Quite literally, this maps over each character in the input, assigns it a value based on the sharpness table, and sums the stack.

# Answer
> 2 votes
# Zsh, 73 bytes

```
a=(O S CU : AV NZ MW)
for c (${(s[])1})(((x=a[(I)*$c*])&&(r+=x-4)))
<<<$r

```

Try it online!

Get the last `(I)`ndex of the glob `*$char*` (with `(I)`, it is zero if not found). If it is non-zero, add to `$r`.

# Answer
> 2 votes
# 05AB1E, ~~39~~ ~~38~~ ~~36~~ ~~34~~ ~~33~~ 28 bytes

```
lε.•3и½:∍äaŠ•sk>4%„Ý§uyåi(]O

```

Try it online! or Verify all test cases (as arranged by @sporeball)

*-5 thanks to @Kevin*

## Explained

```
Original: lε.•3и½:∍äaŠ•sk>4%„Ý§uyåi(]O
Uncompressed: lε"anm vzw cso u"sk>4%"cosu"yåi(]O

l               | Take the implicit input and lowercase it.
ε               | Map the following to this input to find the sharpness of each letter:
"anm vzw cso u" |   Push the string "anm vzw cso u", representing the sharpness of each
                |   letter. They are arranged in a way such the index of the character
                |   is retrivable via mathematical caluclation.
                |
sk              |   Swap this string, and the mapping item, and find the index of the
                |   item within the big string
                |
>4%             |   Increment the value, and then modulo 4 it in order to find the "raw"
                |   sharpness of the string. The result will be in the range [0, 3]
                |
"cosu"          |   Now comes the part where we determine if the sharpness needs to be
                |   negated or not. First, we push a string containing all letters that
                |   have negative sharpness
                |
yå              |   We now push the letter being mapped, and test to see if it is in the
                |   aforementioned string
                |
i(]             |   If it is in the string, negate the sharpness value. After that,
                |   close the if-statement and the loop
                |
O               | Summate the stack and implicitly output the total sharpness.

```

## 05AB1E, 22 bytes

```
.•7ùZ9£nDн•#εXlSk>}O®β

```

Try it online!

A port of the Jelly answer suggested by @Kevin.

# Answer
> 2 votes
# Perl 5 `-p`, 48 bytes

```
$_=y/AV//+2*y/NZ//+3*y/MW//-y/CUSO//-y/SO//-y;O;

```

Try it online!

# Answer
> 1 votes
# Bash \+ GNU utilities, ~~100~~ \\$\cdots\\$ ~~92~~ 91 bytes

```
sed 's/[AV]/+1/g
s/[NZ]/+2/g
s/[MW]/+3/g
s/[CU]/-1/g
s/S/-2/g
s/O/-3/g
s/[A-Z]//g'<<<0$1|bc

```

Try it online!

# Answer
> 1 votes
# Pyth, 28 bytes

```
J"MNA CSOWZV U"sm-3%xJd7@#JQ

```

Try it online!

# Answer
> 1 votes
# Ruby, 70 bytes

```
->s{'OAVNZMWCUS'.chars.zip(1226655440.digits).sum{s.count(_1)*(_2-3)}}

```

Try it online! (3 bytes longer because TIO doesn't suppoort ruby 2.7 `_1` syntax)

# Answer
> 1 votes
# C (gcc), ~~88~~ 87 bytes

Saved a byte thanks to ceilingcat!!!

```
char*t="O_S_CU__AVNZMW",*i;v;f(char*s){for(v=0;*s;v+=i?i-t-6>>1:0)i=index(t,*s++);v=v;}

```

Try it online!

# Answer
> 1 votes
# Java (OpenJDK 8), 205 bytes

```
int u(String s){if(s.length()>0){int n=0;switch(s.charAt(0)){case'M':case'W':n++;case'N':case'Z':n++;case'A':case'V':n+=4;case'O':n--;case'S':n--;case'C':case'U':n--;}return n+u(s.substring(1));}return 0;}

```

Try it online!

# Answer
> 1 votes
# T-SQL, 133 bytes

Added some line changes to make it readable

```
SELECT
SUM(iif('P'=type,nullif(substring(
translate(@,'AVNZMWCUSO','4455662210'),
number,1),substring(@,number,1))-3,0))
FROM spt_values

```

**Try it online**

# Answer
> 1 votes
# Add++, 49 bytes

```
D,k,@,"MCNSAO_WUZ_V"$€=12Rz€¦*bM-1+4*7%3$_
L,€kBs

```

Try it online!

An implementation of xnor's formula, go upvote that.

## How it works

The second line defines the main function which runs the helper function `k` over ach character in the input, then sums the result.

`k` works as follows:

```
D,k,@,"MCNSAO_WUZ_V"$€=12Rz€¦*bM-1+4*7%3$_ ; Monadic function, takes a single character **s**
					   ;    and returns the sharpness of **s**
					   ; For example, **s** = 'C'		 		STACK = ['C']
      "MCNSAO_WUZ_V"			   ; Push this string 			 		STACK = ['C' 'MCNSAO_WUZ_V']
                    $€=			   ; Check each character for equality with **s**		STACK = [[0 1 0 0 0 0 0 0 0 0 0 0]]
		       12R		   ; Push [1 2 3 4 5 6 7 8 9 10 11 12]			STACK = [[0 1 0 0 0 0 0 0 0 0 0 0] [1 2 3 4 5 6 7 8 9 10 11 12]]
			  z		   ; Zip arrays						STACK = [[[0 1] [1 2] [0 3] [0 4] [0 5] [0 6] [0 7] [0 8] [0 9] [0 10] [0 11] [0 12]]]
			   €¦*		   ; Product of each					STACK = [[0 2 0 0 0 0 0 0 0 0 0 0]]
			      bM	   ; Maximum (call the result **r**)			STACK = [2]
				-1+4*7%3$_ ; Push 3 - ((**r** - 1) * 4 % 7)				STACK = [-1]

```

# Answer
> 0 votes
# Perl 5 \+ `-pF`, 39 bytes

```
$\+=y/OSUBANMCBVZW/0-62-6/&&$_-3for@F}{

```

Try it online!

## Explanation

For each character in the input (stored in `@F` via `-F`) we add to `$\` (defaults to `''`, implicitly output as the last argument for calls to `print`, which is triggered as part of `-p`) the value of `$_-3`, if we have `tr`anslated (`y///` is a synonym for `tr///`) any char in `$_` (the current char taken from `for@F`) using `OSUBANM` to `0-6` and `CBVZW` to `2-6`.

# Answer
> 0 votes
# SimpleTemplate, 118 bytes

Yes, not short at all. :(
My language has absolutely no way what-so-ever of creating an array with keys and values defined, so, everything has to be generated.

```
{@setA 1,1,2,2,3,3,-1,-1,-2,-3}{@setL"AVNZMWCUSO"}{@eachL}{@setA.[_]A.[__]}{@/}{@eachargv.0}{@incbyA.[_]R}{@/}{@echoR}

```

This simply outputs the sharpness of the word.

---

**Ungolfed**

The code above is just a mess! Here's a readable version:

```
{@set rates 1,1,2,2,3,3,-1,-1,-2,-3}
{@set letters "AVNZMWCUSO"}
{@each letters as letter key i}
    {@set rates.[letter] rates.[i]}
{@/}

{@set result 0}

{@each argv.0 as char}
    {@inc by rates.[char] result}
{@/}
{@echo result}

```

Should be fairly easy to understand.

The `{@inc by rates.[char] result}` will increment the `result` by `rates.[char]` (similar to `result += rates[char]` on other languages).

---

You can try this on http://sandbox.onlinephpfunctions.com/code/54adfe0b61fe1a12f3be085d0e058123a7842627
There you have the golfed version, ungolfed and a function implementation (the `{@echo result}` is replaced with `{@return result}`).

---
Tags: code-golf, string
---


title: Judge a book by its cover

text:
# Question
Title: Judge a book by its cover
## Overview

The cover of a book will be provided in the following ASCII format:

```
______
|    |
|    |
|    |
|    |
------

```

The input can be in any reasonable format (eg. a list of strings, a nested list of characters, etc.)

Inside the "borders" of the cover, other printable ascii characters might appear, which contribute to the "popularity index" (the definition of which has been completely made up for this challenge).

### Popularity Index

Let the *popularity index* of a book be the number of unique characters that appear on the book cover (this does not include space characters or the edges of the cover). A book may have no unique characters on the cover (the cover is blank), in which case the popularity index is **0**.

**Examples**

```
______
|\/ /|
|/\/ |
| /\/|
|/ /\|
------

```

Two unique characters (`/` and `\`) so the popularity index is **2**.

```
______
| / /|
|/ / |
| / /|
|/ / |
------

```

One unique character (`/`), so the popularity index is **1**

```
______
|    |
|    |
|    |
|    |
------

```

No unique characters, the popularity index is **0**

```
______
|\^$@|
|/\/ |
| 456|
|/ /\|
------

```

8 unique characters, so the popularity index is **8**.

```
______
|\^$@|
|987 |
| 456|
|/hi!|
------

```

14 unique characters, so the popularity index is **14**.

```
______
|////|
|////|
|////|
|////|
------

```

One unique character (`/`), so the popularity index is **1**.

### Damaged Books

The edges of the book might also be damaged:

```
Top         Left        Right       Bottom

_~____      ______      ______      ______
|    |      |    |      |    |      |    |
|    |      |    |      |    |      |    |
|    |  or  {    |  or  |    }  or  |    |
|    |      |    |      |    |      |    |
------      ------      ------      ---~--

```

The book may have several of these "scratches". The scratches at the top and bottom will always be represented by a `~`, while the scratches on the left and right will always be represented by a `{` and `}` respectively. Each scratch will decrease the popularity index by **1**.

As a result, it is possible for a book to have a **negative** popularity index.

## Task

Given an ASCII representation of a book cover in the format described above, determine the "popularity index" of the book

### Assumptions

* You can assume that the characters `|`, `_`, and `-` will not appear elsewhere on the book cover (only on the edges). However, the scratch characters (`{`, `}`, and `~`) **may** appear on the book cover in which case they should be treated as any other unique character on the cover.
* All characters appearing on the cover will be printable ascii
* Note that spaces do not count as a unique character. As the examples above show, a "blank" cover is one that only contains spaces.
* The book will always be the same size (height and width are fixed). Hence, the popularity index will never exceed **16**.

### Scoring

This is . Happy golfing!

**More Examples**

```
______
|{. }|
|/. /|
|/. /}
|/. /|
------

```

4 unique characters (`{`, `}`, `.` and `/`) and one scratch (`}` on the right) so the popularity index is **3**.

```
______
{    |
| .. |
|    }
{    |
--~~--

```

One unique character (`.`) and 5 scratches so the popularity index is **-4**.

### Test Cases

```
______
|    |
|    |
|    |
|    |
------    ->    0

______
|\/ /|
|/\/ |
| /\/|
|/ /\|
------    ->    2

______
| / /|
|/ / |
| / /|
|/ / |
------    ->    1

______
|\^$@|
|/\/ |
| 456|
|/ /\|
------    ->    8

______
|!!!!|
|+  +|
| ** |
|<**>|
------    ->    5

______
|\^$@|
|987 |
| 456|
|/hi!|
------    ->    14

______
|THIS|
| is |
| a. |
|BOOK|
------    ->    11

______
|////|
|////|
|////|
|////|
------    ->    1

______
|abcd|
|efgh|
|ijkl|
|mnop|
------    ->    16

______
|{. }|
|/. /|
|/. /}
|/. /|
------    ->    3

______
{    |
| .. |
|    }
{    |
--~~--    ->    -4

~~~~~~
{    }
{    }
{    }
{    }
~~~~~~    ->    -20

______
|~~~~|
|.   |
{....}
|.   |
------    ->    0

______
|{~~}|
|    |
|    |
|    |
------    ->    3

__~~__
|{~~}|
|    |
|    |
{    |
-----~    ->    -1

```

# Answer
# JavaScript (ES6),  ~~75 74~~  73 bytes

Takes a single string of 36 characters as input, i.e. without any line feed.

```
s=>s.replace(o=/[^ |_-]/g,(c,n)=>t+=n*9%56%37%9&1?o[c]^(o[c]=1):-1,t=0)|t

```

Try it online!

### How?

We filter out spaces, pipes, underscores and hyphens:

```
/[^ |_-]/g

```

It means that we're going to match only:

* scratches on the border (-1 point)
* or non-space characters on the cover (+1 point the first time each of them appears)

Given the 0-indexed position \\$n\\$ of the character in the input string, the shortest solution I've found so far to figure out if we're located on the border or on the cover is the following convoluted modulo chain:

$$\big(((9\times n)\bmod 56)\bmod 37\big)\bmod 9$$

which gives:

$$\begin{pmatrix} 0&1&2&3&4&5\\ 6&7&8&9&10&11\\ 12&13&14&15&16&17\\ 18&19&20&21&22&23\\ 24&25&26&27&28&29\\ 30&31&32&33&34&35 \end{pmatrix} \rightarrow \begin{pmatrix} \color{blue}0&\color{blue}0&\color{blue}0&\color{blue}0&\color{blue}0&\color{blue}8\\ \color{blue}8&7&7&7&7&\color{blue}6\\ \color{blue}6&5&5&5&5&\color{blue}4\\ \color{blue}4&3&3&3&3&\color{blue}2\\ \color{blue}2&1&1&1&1&\color{blue}0\\ \color{blue}0&\color{blue}0&\color{blue}8&\color{blue}8&\color{blue}8&\color{blue}8 \end{pmatrix}$$

With even numbers on the border and odd numbers on the cover.

### Generalization of the formula

Given a square matrix of width \\$w\>3\\$ whose cells are indexed from \\$0\\$ to \\$w^2-1\\$, the \\$n\\$-th cell is located on a border iff the result of the following expression is even:

$$\big(((p\times n)\bmod m\_0)\bmod m\_1\big)\bmod p$$

with:

$$p=2w-3$$ $$m\_0=2\cdot (w-1)^2+w$$ $$m\_1=2\cdot (w-2)^2+w-1$$

Try it online!

NB: This is an empirical result that I didn't attempt to prove.
> 17 votes

# Answer
# Python 2, 73 bytes

Input is taken as a 2D list \\$ b \\$. Output is the popularity index of \\$ b \\$.

```
lambda b:len({j.pop(1)for j in b[1:5]*4}-{' '})-sum(map(`b`.count,'{}~'))

```

Try it online!

---

The left part of the expression does two things: adds up the popularity index inside the cover, and removes its characters. The right part subtracts the damaged characters from the remaining characters.
> 12 votes

# Answer
# , 51 41 40 bytes

```
_1#.1#.(+./~#:33)e.&'{}~'`(' '~:~.)/.&,]

```

Try it online!

*-11 bytes thanks to Bubbler!*

*Both the function table trick to compress `#:@68208171135` down to `+./~@#:@33`, and the "negative one base trick" are due to them.*

## how

1. `+./~@#:@33` Let's begin with this phrase, which produces:

```
1 1 1 1 1 1
1 0 0 0 0 1
1 0 0 0 0 1
1 0 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1

```

How? 33 in binary `#:@33` is `1 0 0 0 0 1`. Then create an "or" function table `+./` of this list with itself. It is easy to verify this will be 1 exactly on the border cells.
2. `/.&,]` Flatten the input and use the mask above to split the input into two groups, using J's Key `/.` adverb:

```
Apply this verb to the              Damage:
1st group, the edges:    -------->  Is each character an
     |                              element of '{}~'?
 ___/____                           Returns a 0-1 list.
 e.&'{}~'`(' '~:~.)
          ^^^^^^^^^
               |                    Reputation:
    And this one to the second -->  Is space not equal
    (the interior)                  to each character
                                    of the uniq? Also
                                    a 0-1 list.

```

We now have two 0-1 lists. For example:

```
Reputation: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
Damage:     1 1 0 1 1

```

J will extend the shorter list to the length of the longer, filling it with zeros:

```
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

```
3. `1#.` Sum rowwise:

```
1 4

```
4. `_1#.` This uses a -1 base as a golfy way to subtract 1 from 4. By definition of base:

```
(1 * -1^1) + (4 * -1^0)
(1 * -1) + (4 * 1)
3

```
> 10 votes

# Answer
# Python 2, 68 bytes

```
lambda s:len(set((s[8:-6]*4)[::7])-{' '})-20+sum(map(s.count,'_|-'))

```

Try it online!

Instead of counting defects on the borders, counts non-defects `_|-` throughout and subtract from 20, using the rule that only the borders can contain these characters. The `(s[8:-6]*4)[::7]` is a nice string-slicing way to extract the characters on the cover without borders.
> 8 votes

# Answer
# 05AB1E, ~~25~~ 22 bytes

```
4Fćˆøí}˜ðKÙg¯˜…~{}S¢O-

```

-3 bytes by taking inspiration of *@JonathanAllan*'s Jelly answer, so make sure to upvote him!

Input as a matrix of characters.

Try it online or verify all test cases.

**Original 25 bytes approach:**

```
|¦¨ε¦¨}ðýê¦gIJ…_|-S¢O20-+

```

Default input as loose lines in STDIN.

Try it online or verify all test cases.

**Explanation:**

```
4F            # Loop 4 times:
  ć           #  Extract head; pop and push remainder-matrix and first line separately
   ˆ          #  Pop and add this first line to the global array
    ø         #  Zip/transpose the remaining matrix; swapping rows/columns
     í        #  Reverse each line
              #  (`øí` basically rotates the matrix once clockwise)
}˜            # After the loop: flatten the remaining matrix
  ðK          # Remove all spaces
    Ù         # Uniquify it
     g        # And pop and push the amount of remaining unique (non-space) characters
¯˜            # Push the global array, and flatten it as well
  …~{}        # Push string "~{}"
      S       # Convert it to a list of characters: ["~","{","}"]
       ¢      # Count each in the flattened global array
        O     # Sum those
-             # Subtract the two from one another
              # (after which the result is output implicitly)

|             # Push all lines of inputs as a list of strings
 ¦¨           # Remove the first and last lines
   ε  }       # Map over each line:
    ¦¨        #  And also remove the first and last character of each line
       ðý     # Join everything together with space delimiter
         ê    # Uniquify and sort the characters
          ¦   # Remove the first character (the space)
           g  # And pop and push its length
I             # Push the input-list of lines again
 J            # Join them all together
  …_|-        # Push string "_|-"
      S       # Convert it to a list of characters: ["_","|","-"]
       ¢      # Count each in the joined input
        O     # Take the sum of those counts
         20-  # Subtract 20 from this
+             # Add the two together
              # (after which the result is output implicitly)

```
> 7 votes

# Answer
# Jelly, 25 bytes

```
Ḣ;ɼȧZṚµ4¡FQḟ⁶,®f“~{}”¤Ẉ_/

```

A full program accepting a single argument as a list of Python strings which prints the result.

**Try it online!** Or see the test-suite.

### How?

```
Ḣ;ɼȧZṚµ4¡FQḟ⁶,®f“~{}”¤Ẉ_/ - Main Link: list of lists of characters (the lines)
      µ4¡                 - repeat this monadic chain four times:
Ḣ                         -   head (gives us the head AND modifies the chain's input)
  ɼ                       -   recall from the register (initially 0) and apply & store:
 ;                        -     concatenate
    Z                     -   transpose the chain's (now modified) input
   ȧ                      -   logical AND (the concatenate result with the transpose, to get us the transpose of the chain's input)
     Ṛ                    -   reverse (together with the transpose this is rotate one quarter)
         F                - flatten (what we have left is the cover's inner characters)
          Q               - de-duplicate
           ḟ⁶             - discard spaces
                     ¤    - nilad followed by link(s) as a nilad:
              ®           -   recall from the register (the cover's edge characters)
               f“~{}”     -   keep only "~{}" characters
             ,            - pair (the two lists of characters)
                      Ẉ   - length of each
                        / - reduce by:
                       _  -   subtraction
                          - implicit print (a list containing only one entry prints just that entry)

```
> 6 votes

# Answer
# Python 3, ~~106~~ ~~102~~ 80 bytes

```
lambda b:len({*(b[8:12]+b[15:19]+b[22:26]+b[29:33])})-21+sum(map(b.count,"-|_"))

```

Try it online!

I know there's a shorter Python answer, and I know that this isn't the most optimal method. But I had come up with a solution which I golfed, and I'm posting it for the sake of completion. *-2 thanks to @Kevin and -2 thanks to OVS*. *A further -22 thanks to @mathjunkie*.
> 5 votes

# Answer
# Python 2, 66 bytes

```
lambda s:len(set((s[8:-6]*4)[::7]+' '))-21+sum(map(s.count,'_|-'))

```

Try it online!

---

A slight improvement over @xnor's answer. Instead of removing spaces from the cover, we *add* spaces to the cover, and then subtract 1.
> 5 votes

# Answer
# APL (Dyalog Unicode), ~~42~~ 35 bytes

-6 thanks to Bubbler.

Anonymous tacit prefix function. Requires `⎕IO←0` (0-based indexing).

```
-⍨/(,∘.⍱⍨6⍴5↑1){≢∪⍣⍺⊢⍵~⊃⍺↓⊂'_|-'}⌸∊

```

Try it online!

**ϵ**nlist (flatten)

`(``){``}⌸` apply the below function to each of the two groups identified by 1s and 0s in:

`5↑1` take five elements from 1; `[1,0,0,0,0]`

`6⍴` cyclically **r**eshape that to length six; `[1,0,0,0,0,1]`

`∘.⍱⍨` NOR-table of that;
`[[0,0,0,0,0,0],`
`[0,1,1,1,1,0],`
`[0,1,1,1,1,0],`
`[0,1,1,1,1,0],`
`[0,1,1,1,1,0],`
`[0,0,0,0,0,0]]`

`,` ravel (flatten)

The following function will be applied to each multiset (0: edge characters; 1: inner characters):

`'_|-'` a string; `"_|-"`

enclose it; `["_|-"]`

`⍺↓` drop 1 element if the set is that of inner characters, otherwise drop 0 elements

get the first element; the above string or `" "` if gone

`⍵~` remove those characters from the edge/inner set

`∪⍣⍺⊢` if inner, then get the unique of that, else leave as-is

tally that

`-⍨/` subtract the first count from the last count
> 4 votes

# Answer
# Charcoal, ~~49~~ 41 bytes

```
≔⪫Ｅ⁶Ｓ¶θＰθＢ⁶ ＷΦＫＡ¬№υκ⊞υ⊟ι⎚Ｉ⊖⁻Ｌυ⁻²⁰ΣＥ-_|№θι

```

Try it online! Link is to verbose version of code. Explanation:

```
≔⪫Ｅ⁶Ｓ¶θ

```

Input the cover.

```
ＰθＢ⁶

```

Print the cover, but immediately erase the border.

```
ＷΦＫＡ¬№υκ⊞υ⊟ι

```

Collect all the unique characters, which always includes a space, as we used that to erase the border. (I feel that I should be able to use `Ｗ⁻ＫＡυ⊞υ⊟ι` but Charcoal crashes when I try.)

```
⎚Ｉ⊖⁻Ｌυ⁻²⁰ΣＥ-_|№θι

```

Clear the canvas and output the popularity, adjusting for the extra space collected and the number of missing border characters in the original string.

I also tried counting the popularity by directly inspecting the string instead of printing it and deleting the border but it turns out that that costs bytes overall.

Previous 49-byte solution does not assume that edge characters only appear on the edge:

```
≔⪫Ｅ⁶Ｓ¶θＰθＢ⁶ ＷΦＫＡ¬№υκ⊞υ⊟ιＰθ↘ＵＯ⁴ ≔ΦＫＡ№{~}ιθ⎚Ｉ⊖⁻ＬυＬθ

```

Try it online! Link is to verbose version of code. Explanation:

```
≔⪫Ｅ⁶Ｓ¶θ

```

Input the cover.

```
ＰθＢ⁶

```

Print the cover, but immediately erase the border.

```
ＷΦＫＡ¬№υκ⊞υ⊟ι

```

Collect all the unique characters, which always includes a space, as we used that to erase the border. (I feel that I should be able to use `Ｗ⁻ＫＡυ⊞υ⊟ι` but Charcoal crashes when I try.)

```
Ｐθ↘ＵＯ⁴

```

Print the cover again, but this time keep only the border.

```
≔ΦＫＡ№{~}ιθ

```

Collect all the `{`, `~` and `}` characters.

```
⎚Ｉ⊖⁻ＬυＬθ

```

Clear the canvas and output the calculated popularity, adjusting for the extra space collected.
> 4 votes

# Answer
# perl -M5.010 -n -0543, 82 bytes

```
$i--for/\}$|^\{|~(?=[-_~]*$)/gm;s/^[-_~]+$|^.|.$//gm;$c{$_}++for/\S/g;say$i+keys%c

```

Try it online!

First, the penalty is calculated by counting `{`s which start a line, `}`s which end a line, and any `~` in the top and bottom lines. We then strip off the boundaries, and count the number of unique non-space characters; the penalty is added to that, to get the final score.

Reads a single cover from `STDIN`, writes the score to `STDOUT`.
> 4 votes

# Answer
# Java (OpenJDK 8), 326 320 319 305 bytes

```
int f(List<Character>[]c){int s=0,i=3;c[0].addAll(c[5]);for(;i>1;)S(50*i---55,c[0]);c[5].clear();for(;i<5;c[5].addAll(c[i++]))s+=c[i].remove(0)-c[i].remove(4);S(32,c[5]);for(;c[5].size()>0;i++)S(c[5].get(0),c[5]);return i-5-c[0].size()+s;}void S(int x,List c){c.removeAll(Collections.singleton((char)x));}

```

Try it online!

THANKS to Muskovets's suggestion of using List (-4), I also omitted the generic type in the second method (List instead of List\< Character\>)

Takes input as List\< Character\>\[\] and outputs an int.

It uses 2 methods (I'm not entirely sure how "allowed" that is)

See inside for comments and ungolfed and alternate solutions (including a single method one).

Interesting part: the ascii values for { | } are 123, 124, 125. That means that this part changes the popularity index by:

for each row: the left char minus the right char

{...} 123 - 125 = -2

{...| 123 - 124 = -1

|...} 124 - 125 = -1

|...| 124 - 124 = 0

It only works with only exactly the given possible inputs, none else (illegal inputs like }...{). Pretty lucky.

This was done with ArrayList, but possibly some other Collection with a shorter name or better methods would be better. Edit: indeed there is: Vector. updated. (Now List)

---

Takes input as String\[\]. Only one method.

# Java (OpenJDK 8), 267 261 bytes

```
int f(String[]c){int s=0,i=4;c[0]=c[0].replace("_","")+c[5].replace("-","");c[5]="";for(;i>0;c[5]+=c[i--].substring(1,5))s+=c[i].charAt(0)-c[i].charAt(5);for(;c[5].trim().length()>0;i++)c[5]=c[5].replace(c[5].trim().substring(0,1),"");return i-c[0].length()+s;}

```

Try it online!
> 4 votes

# Answer
# Perl 5 \+ `-p0 -MList::Util+uniq`, 55 bytes

```
s/^.{5}|.
.|.{5}$/$\-=$&=~y!~{}!!;""/ge;$\+=uniq/\S/g}{

```

Try it online!
> 3 votes

# Answer
# PHP, ~~104~~ 93 bytes

Original code from yesterday:

```
while($s<35+$c=ord($b[$t=$s++]))$p-=$t>5&$s<31?$t%6?$s%6?0&$i[$c]=1:$c:-$c:$c%5;echo$p+count($i)-$i[32];

```

Try it online!
Improved with a `mod`-expression from @Arnauld, cf. his solution.

```
for(;$s<36;$s++)$p-=$s*9%56%37%9&1?!$i[$b[$s]]=1:ord($b[$s])%29%8>0;echo$p+count($i)-$i[" "];

```

Try it online!

## Explanation

* I was using the fact that char codes of intact top and bottom edges are `%5=0`, and left and right edges have char codes that are in sequence.
* I've now researched the char codes of the six edge chars a little better.
Try `[45,95,124,123,125,126]%18%15`. There are also other options like `$c%29%8==0` and so on.

## Please Help Me Get Better

I appreciate any comments or suggestions.
> 3 votes

# Answer
## Bash \+ standard tools 121 Bytes

```
bc<<<$(sed '1d;$d;s/.//;s/.$//' $1|grep -o '[^ ]'|sort -u|wc -l)-$(sed -E '2,${$!s/(.)..../\1/}' $1|tr -cd '[~{}]'|wc -c)

```

Input is a file of the book.

Try it online! (+6 bytes because input needs to be a string here)
> 1 votes

# Answer
# C (gcc), 174 bytes

```
//N(c)=p-=*s++!=c
p,v,i,j,k;f(char*s){char u[16]={};for(v=p=0,i=6;i--;N(95));for(j=4;j--;N(124))for(N(124),i=4;i--;)strchr(u,k=*s++-32)||(u[v++]=k);for(i=6;i--;N(45));s=p+v;}

```

Try it online!

Pretty standard: I count the number of unique characters in the cover (which is built up in a string), then deduct the amount of damage.
> 1 votes

# Answer
# Erlang (escript), 184 bytes

Just a port of Lyxal's Python answer. (Where's the unique function in Erlang?)

```
u([H|T])->[H]++u([I||I<-T,I/=H]);u(X)->X.
f(X)->length(u(lists:flatten([lists:droplast(tl(I))||I<-lists:droplast(tl(string:split(X,"
",all)))])))-21+length([I||I<-X,([I]--"_|-")==[]]).

```

Try it online!
> 0 votes

# Answer
# Ruby, ~~101~~ 98 bytes

```
->s{a,*b,c=s.lines;(b.flat_map{x,*y,z,_=_1.chars;a+=x+z;y}|[' ']).size-22+(a+c).tr('{}~','').size}

```

### 100 byte version because TIO doesn't support ruby 2.7

```
->s{a,*b,c=s.lines;(b.flat_map{|i|x,*y,z,_=i.chars;a+=x+z;y}|[' ']).size-22+(a+c).tr('{}~','').size}

```

Try it online!
> 0 votes

---
Tags: code-golf
---


title: Distance between two points on the Moon

text:
# Question
Title: Distance between two points on the Moon
Given latitude/longitude of two points on the Moon `(lat1, lon1)` and `(lat2, lon2)`, compute the distance between the two points in kilometers, by using **any formula** that gives the same result as the haversine formula.

## Input

* Four integer values `lat1, lon1, lat2, lon2` in degree (angle) or
* four decimal values `ϕ1, λ1, ϕ2, λ2` in radians.

## Output

Distance in kilometers between the two points (decimal with any precision or rounded integer).

## Haversine formula

where

* `r` is the radius of the sphere (assume that the Moon's radius is 1737 km),
* `ϕ1` latitude of point 1 in radians
* `ϕ2` latitude of point 2 in radians
* `λ1` longitude of point 1 in radians
* `λ2` longitude of point 2 in radians
* `d` is the circular distance between the two points

(source: https://en.wikipedia.org/wiki/Haversine\_formula)

## Other possible formulas

* `d = r * acos(sin ϕ1 sin ϕ2 + cos ϕ1 cos ϕ2 cos(λ2 - λ1))` *@miles*' formula.
* `d = r * acos(cos(ϕ1 - ϕ2) + cos ϕ1 cos ϕ2 (cos(λ2 - λ1) - 1))` *@Neil*'s formula.

## Example where inputs are degrees and output as rounded integer

```
42, 9, 50, 2  --> 284
50, 2, 42, 9  --> 284
4, -2, -2, 1  --> 203
77, 8, 77, 8  --> 0
10, 2, 88, 9  --> 2365

```

## Rules

* The input and output can be given in any convenient format.
* Specify in the answer whether the inputs are in **degrees** or **radians**.
* No need to handle **invalid latitude/longitude values**
* Either a full program or a function are acceptable. If a function, you can return the output rather than printing it.
* If possible, please include a link to an online testing environment so other people can try out your code!
* Standard loopholes are forbidden.
* This is so all usual golfing rules apply, and the shortest code (in bytes) wins.

# Answer
# Wolfram Language (Mathematica), 48 bytes

```
ArcCos[Sin@#*Sin@#3+Cos[#2-#4]Cos@#*Cos@#3]1737&

```

Try it online!

Uses the formula `d = r * acos( sin ϕ1 sin ϕ2 + cos ϕ1 cos ϕ2 cos(λ2 - λ1) )` where `r = 1737`
> 6 votes

# Answer
# \+ geosphere, ~~54~~ 47 bytes

```
function(p,q)geosphere::distHaversine(p,q,1737)

```

Try it online!

Takes input as 2-element vectors of `longitude,latitude` in degrees. TIO doesn't have the `geosphere` package but rest assured that it returns identical results to the function below.

Thanks to Jonathan Allan for shaving off 7 bytes.

# , 64 bytes

```
function(p,l,q,k)1737*acos(sin(p)*sin(q)+cos(p)*cos(q)*cos(k-l))

```

Try it online!

Takes 4 inputs as in the test cases, but in radians rather than degrees.
> 6 votes

# Answer
# APL (Dyalog Unicode), ~~40~~ 35 bytesSBCS

Anonymous tacit function. Takes {ϕ₁,λ₁} as left argument and {ϕ₂,λ₂} as right argument.

Uses the formula 2 r √(sin²((ϕ₁-ϕ₂)2) + cos ϕ₁ cos ϕ₂ sin²((λ₁ – λ₂)2))

```
3474×¯1○.5*⍨1⊥(×⍨1○2÷⍨-)×1,2×.○∘⊃,¨

```

Try it online! (the `r` function converts degrees to radians)

---

concatenate corresponding elements; {{ϕ₁ , ϕ₂} , {λ₁ , λ₂}}

pick the first; {ϕ₁ , ϕ₂}

then

`2×.○` product of their cosines; cos ϕ₁ cos ϕ₂
lit. dot "product" but with trig function selector (2 is cosine) instead of multiplication and times instead of plus

`1,` prepend 1 to that; {1 , cos ϕ₁ cos ϕ₂}

`(` multiply that by the result of applying following function to {ϕ₁ , λ₁} and {ϕ₂ , λ₂}:

`-` their differences; {ϕ₁ - ϕ₂ , λ₁ - λ₂}

`2÷⍨` divide that by 2; {(ϕ₁ - ϕ₂)2 , (λ₁ - λ₂)2}

`1○` sine of that; {sin((ϕ₁ - ϕ₂)2) , sin((λ₁ - λ₂)2)}

`×⍨` square that (lit. self-multiply); {sin²((ϕ₁ - ϕ₂)2) , sin²((λ₁-λ₂)2)}

Now we have {sin²((ϕ₁ - ϕ₂)2) , cos ϕ₁ cos ϕ₂ sin²((λ₁ - λ₂)2)}

`1⊥` sum that (lit. evaluate in base-1); sin²((ϕ₁-ϕ₂)2) + cos ϕ₁ cos ϕ₂ sin²((λ₁ - λ₂)2)

`.5*⍨` square-root of that (lit. raise that to the power of a half)

`¯1○` arcsine of that

`3474×` multiply that by this

---

The function to allow input in degrees is:

```
○÷∘180

```

`÷180` argument divided by 180

multiply by π
> 5 votes

# Answer
# JavaScript (ES7), 90 bytes

*Note: see @OlivierGrégoire's post for a much shorter solution*

A direct port of TFeld's answer. Takes input in radians.

```
(a,b,c,d,M=Math)=>3474*M.asin((M.sin((c-a)/2)**2+M.cos(c)*M.cos(a)*M.sin((d-b)/2)**2)**.5)

```

Try it online!

# Using the infamous `with()`, 85 bytes

*Thanks to @l4m2 for saving 6 bytes*

```
with(Math)f=(a,b,c,d)=>3474*asin((sin((c-a)/2)**2+cos(c)*cos(a)*sin((d-b)/2)**2)**.5)

```

Try it online!
> 5 votes

# Answer
# JavaScript (Node.js), 65 bytes

```
(a,b,c,d,C=Math.cos)=>1737*Math.acos(C(a-c)+C(a)*C(c)*(C(d-b)-1))

```

Try it online!

Based on Kevin Cruijssen's answer, Miles' and Neil's comments, and upon request of Arnauld.
> 5 votes

# Answer
# Python 2, 95 bytes

```
lambda a,b,c,d:3474*asin((sin((c-a)/2)**2+cos(c)*cos(a)*sin((d-b)/2)**2)**.5)
from math import*

```

Try it online!

Takes input in radians.

---

Old version, before i/o was slacked: Takes input as integer degrees, and returns rounded dist

# Python 2, 135 bytes

```
lambda a,b,c,d:int(round(3474*asin((sin((r(c)-r(a))/2)**2+cos(r(c))*cos(r(a))*sin((r(d)-r(b))/2)**2)**.5)))
from math import*
r=radians

```

Try it online!
> 4 votes

# Answer
# Japt, ~~55~~ 50 bytes

```
MsU *MsW +McU *McW *McX-V
ToMP1/7l¹ñ@McX aUÃv *#7

```

Not necessarily quite as precise as the other answers, but boy did I have fun with this one. Allow me to elaborate.
While in most languages, this challenge is quite straightforward, Japt has the unfortunate property that there is no built-in for neither arcsine nor arccosine. Sure, you can embed Javascript in Japt, but that would be what ever the opposite of Feng Shui is.

All we have to do to overcome this minor nuisance is approximate arccosine and we're good to go!

The first part is everything that gets fed into the arccosine.

```
MsU *MsW +McU *McW *McX-V
MsU                        // Take the sine of the first input and
    *MsW...                // multiply by the cos of the second one etc.

```

The result is implicitly stored in `U` to be used later.

Following that, we need to find a good approximation for arccosine. Since I'm lazy and not that good with math, we're obviously just going to brute-force it.

```
ToMP1/7l¹ñ@McX aUÃv *#7
T                       // Take 0
 o                      // and create a range from it
  MP                    // to π
    1/7l¹               // with resolution 1/7!.
         ñ@             // Sort this range so that
           McX          // the cosine of a given value
               aU       // is closest to U, e.g. the whole trig lot
                        // we want to take arccosine of.
                 Ã      // When that's done,
                  v     // get the first element
                    *#7 // and multiply it by 1737, returning implicitly.

```

We could've used any large number for the generator resolution, manual testing showed `7!` is sufficiently large while being reasonably fast.

Takes input as radians, outputs unrounded numbers.

Shaved off five bytes thanks to Oliver.

Try it online!
> 4 votes

# Answer
# Java 8, ~~113~~ ~~92~~ ~~88~~ 82 bytes

```
(a,b,c,d)->1737*Math.acos(Math.cos(a-c)+Math.cos(a)*Math.cos(c)*(Math.cos(d-b)-1))

```

Inputs `a,b,c,d` are `ϕ1,λ1,ϕ2,λ2` in radians.

-21 bytes using *@miles*' shorter formula.
-4 bytes thanks to *@OlivierGrégore* because I still used `{Math m=null;return ...;}` with every `Math.` as `m.`, instead of dropping the `return` and use `Math` directly.
-6 bytes using *@Neil*'s shorter formula.

Try it online.

**Explanation:**

```
(a,b,c,d)->                  // Method with four double parameters and double return-type
  1737*Math.acos(            //  Return 1737 multiplied with the acos of:
   Math.cos(a-c)             //   the cos of `a` minus `c`,
   +Math.cos(a)*Math.cos(c)  //   plus the cos of `a` multiplied with the cos of `c`
   *(Math.cos(d-b)-1))       //   multiplied with the cos of `d` minus `b` minus 1

```
> 3 votes

# Answer
# Ruby, ~~87 70 69~~ 68 bytes

```
->{extend Math;1737*acos(cos(_1-_3)+cos(_1)*cos(_3)*(cos(_4-_2)-1))}

```

### Unfortunately, TIO doesn't support `_1` syntax so for TIO, 69 bytes

```
->a,b,c,d{extend Math;1737*acos(cos(a-c)+cos(a)*cos(c)*(cos(d-b)-1))}

```

Try it online!

Now using Neil's method, thanks to Kevin Cruijssen.
> 3 votes

# Answer
# Haskell, ~~68 66 52~~ 51 bytes

```
s=cos;(a!b)c d=1737*acos(s(a-c)+s a*s c*(s(d-b)-1))

```

Try it online!

-1 byte thanks to BMO
> 3 votes

# Answer
# Jelly,  ~~23 22~~  18 bytes

-4 bytes thanks to miles (use of `{` and `}` while using their formula.

```
;I}ÆẠP+ÆSP${ÆA×⁽£ġ

```

A dyadic function accepting `[ϕ1, ϕ2,]` on the left and `[λ1, λ2]` on the right in **radians** that returns the result (as floating point).

**Try it online!**

---

Mine... (also saved a byte here by using a `{`)

```
,IÆẠCH;ÆẠ{Ḣ+PƊ½ÆṢ×⁽µṣ

```

Try it online
> 2 votes

# Answer
# MATLAB with Mapping Toolbox, 26 bytes

```
@(x)distance(x{:})*9.65*pi

```

Anonymous function that takes the four inputs as a cell array, in the same order as described in the challenge.

Note that this gives exact results (assuming that the Moon radius is 1737 km), because `1737/180` equals `9.65`.

Example run in Matlab R2017b:
> 2 votes

# Answer
# Python 3, ~~119~~ 103 bytes

This uses degrees.

```
from math import*
def f(L):a,o,A,O=map(radians,L);return 1737*acos(cos(a-A)+cos(a)*cos(A)*(cos(O-o)-1))

```

**Try it online!**
> 1 votes

# Answer
# C (gcc), ~~100~~ ~~88~~ ~~65~~ 64 bytes

88 → 65 using *@miles' formula*
65 → 64 using *@Neil's formula*

```
#define d(w,x,y,z)1737*acos(cos(w-y)+cos(w)*cos(y)*(cos(z-x)-1))

```

Try it online!
> 1 votes

# Answer
# Python 3, 79 bytes

```
from geopy import*
lambda a,b:distance.great_circle(a,b,radius=1737).kilometers

```

TIO doesn't have geopy.py
> 1 votes

# Answer
# APL (Dyalog Unicode), 29 bytesSBCS

Complete program. Prompts stdin for {ϕ₁,ϕ₂} and then for {λ₁,λ₂}. Prints to stdout.

Uses the formula r acos(sin ϕ₁ sin ϕ₂ + cos(λ₂ – λ₁) cos ϕ₁ cos ϕ₂)

```
1737×¯2○+/(2○-/⎕)×@2×/1 2∘.○⎕

```

Try it online! (the `r` function converts degrees to radians)

---

prompt for {ϕ₁,ϕ₂}

`1 2∘.○` Cartesian trig-function application; {{sin ϕ₁,sin ϕ₂} , {cos ϕ₁,cos ϕ₂}}

`×/` row-wise products; {sin ϕ₁ sin ϕ₂ , cos ϕ₁ cos ϕ₂}

`(``)×@2` at the second element, multiply the following by that:

prompt for {λ₁,λ₂}

`-/` difference between those; λ₁ – λ₂

`2○` cosine of that; cos(λ₁ – λ₂)

Now we have {sin ϕ₁ sin ϕ₂ , cos(λ₁ – λ₂) cos ϕ₁ cos ϕ₂}

`+/` sum; sin ϕ₁ sin ϕ₂ + cos(λ₁ – λ₂) cos ϕ₁ cos ϕ₂

`¯2○` cosine of that; cos(sin ϕ₁ sin ϕ₂ + cos(λ₁ – λ₂) cos ϕ₁ cos ϕ₂)

`1737×` multiply r by that; 1737 cos(sin ϕ₁ sin ϕ₂ + cos(λ₁ – λ₂) cos ϕ₁ cos ϕ₂)

---

The function to allow input in degrees is:

```
○÷∘180

```

`÷180` argument divided by 180

multiply by π
> 1 votes

# Answer
# Excel, 53 bytes

```
=1737*ACOS(COS(A1-C1)+COS(A1)*COS(C1)*(COS(D1-B1)-1))

```

Using @Neil's formula. Input in Radians.
> 1 votes

# Answer
# Lobster, 66 bytes

```
def h(a,c,b,d):1737*radians arccos a.sin*b.sin+a.cos*b.cos*cos d-c

```

Uses miles's formula, but input is in degrees. This adds extra step of converting to radians before multiplying by radius.
> 1 votes

# Answer
# PHP, 88 bytes

*Port of Oliver answer*

```
function f($a,$b,$c,$d,$e=cos){return 1737*acos($e($a-$c)+$e($a)*$e($c)*($e($d-$b)-1));}

```

Try it online!
> 1 votes

# Answer
# SmileBASIC, 60 bytes

```
INPUT X,Y,S,T?1737*ACOS(COS(X-S)+COS(X)*COS(S)*(COS(T-Y)-1))

```
> 1 votes

# Answer
# Wolfram Language (Mathematica), 66 bytes

Clearly the other Wolfram Language golfers only care about *bytes*. *This* program uses the beauty of Mathematica.

```
GeoDistance@@Map[#~GeoPosition~Entity["PlanetaryMoon","Moon"]&,#]&

```

Either I am misusing TIO, or it doesn't work there. This works on my machine, though.
> 1 votes

---
Tags: code-golf, math, geometry, trigonometry
---


# Question
Title: Extract words with clue numbers in a Crossword puzzle
Related: Read a crossword

## Task

Given a completed Crossword puzzle, extract the words in it with their respective clue numbers, with "across" (horizontal) and "down" (vertical) words grouped and ordered like a real crossword puzzle.

The words are numbered in the row-major order of their first letters. If an "across" word and a "down" word share the first letter, the two words share one number. (As in regular Crossword, single-letter words don't count; they should not be numbered or included in the output.)

The input is given as a character matrix (or equivalent), with letters being uppercase (or lowercase if you want) and non-letter cells being blank. You can assume that single-letter islands won't appear in the input. If you want, you can assume the grid is rectangular (shorter rows are padded with spaces).

The output must be clearly grouped into "across" and "down" (you don't need to return or print these strings though), and the words must be ordered in the increasing order of the clue number (see test cases).

Standard rules apply. The shortest code in bytes wins.

## Test cases

```
Input:
MESS
YAWN
 SAID
 TYPO
Output:
Across: 1. MESS 5. YAWN 6. SAID 8. TYPO
Down: 1. MY 2. EAST 3. SWAY 4. SNIP 7. DO

Input:
   RECURS
  PARAPET
 TRIANGLE
COOLS RAW
HUTS MATE
ORE CODED
INCLUDES
RETIRES
SYSTEM
Output:
Across: 1. RECURS 7. PARAPET 8. TRIANGLE 9. COOLS 10. RAW 11. HUTS
        12. MATE 13. ORE 14. CODED 15. INCLUDES 17. RETIRES 18. SYSTEM
Down: 1. RAILS 2. ERAS 3. CAN 4. UPGRADES 5. RELATES 6. STEWED
      7. PROTECTS 8. TOURNEY 9. CHOIRS 12. MODEM 14. CURE 16. LIT

Input:
MICROWAVE
U       S
M OCEAN C
M  OWL  A
I SWELL P
E       E
SCHEDULES
Output:
Across: 1. MICROWAVE 3. OCEAN 7. OWL 8. SWELL 9. SCHEDULES
Down: 1. MUMMIES 2. ESCAPES 4. COW 5. EWE 6. ALL

Input:
TAB
A U
BUBBLE
  B O
  LOVED
  E E
Output:
Across: 1. TAB 3. BUBBLE 5. LOVED
Down: 1. TAB 2. BUBBLE 4. LOVE

```

# Answer
> 4 votes
# Charcoal, 118 bytes

```
ＷＳ⊞υιＰ⪫υ¶≔⟦⟧θＦυ«Ｆι«Ｆ‹ κ«≔✂ιⅈＬι¹η≔⪫ＫＤ⁻Ｌυⅉ↓ωζ≡÷⌕2374ce6⍘↨ＥＫＶ‹ μ²φ³¦²⊞θ⟦ηζ⟧¹⊞θ⟦ηω⟧⁰⊞θ⟦ωζ⟧»→»⸿»⎚Ｅ²⪫ＥΦＥθ⟦⊕μ§⪪§λι ⁰⟧§λ¹⪫λ ¦

```

Try it online! Link is to verbose version of code. Takes input as a rectangular string of newline-terminated lines. Explanation:

```
ＷＳ⊞υιＰ⪫υ¶

```

Input the rectangle and print it to the canvas.

```
≔⟦⟧θ

```

Start off with no clues.

```
Ｆυ«Ｆι«

```

Loop over the rows and columns.

```
Ｆ‹ κ«

```

If the current character is not a space, then...

```
≔✂ιⅈＬι¹η

```

Get the substring of the current line starting at this character.

```
≔⪫ＫＤ⁻Ｌυⅉ↓ωζ

```

Get the substring of the current column starting at this character by reading it from the canvas.

```
≡÷⌕2374ce6⍘↨ＥＫＶ‹ μ²φ³

```

Check which orthogonally adjacent characters are spaces.

```
²⊞θ⟦ηζ⟧

```

If only the characters to the left and above are spaces, then a word starts both across and down.

```
¹⊞θ⟦ηω⟧

```

Otherwise if the character to the left is a space but the character to the right is not, then a word starts across but not down.

```
⁰⊞θ⟦ωζ⟧

```

Otherwise if the character above is a space but the character below is not, then a word starts down but not across.

```
»→»⸿»

```

Move on to consider the next character on each iteration.

Clear the canvas.

```
Ｅ²⪫ＥΦＥθ⟦⊕μ§⪪§λι ⁰⟧§λ¹⪫λ ¦

```

Map over the across and down clues, numbering them all, but keeping only those clues with words in the respective direction.

(Out of interest I tried using just string manipulation instead of canvas operations but that cost 29 bytes.)

# Answer
> 2 votes
# Python 2, ~~284~~ ~~283~~ ~~281~~ ~~272~~ ~~267~~ 263 bytes

*-2 bytes thanks to @Noodle9 for suggesting a different output format*

```
x=input()
A=[];D=[]
d=1;b='!'
i=j=0
L=len
while i<L(x):r=x[i];h=(r[j:].split()or b)[0];c=L(h)*(j<1or-~-q)>1;g=(''.join(r[j]for r in x[i:]).split()or b)[0];q=r[j]>b;a=L(g)*q*(i<1or x[i-1][j]<b)>1;D+=a*[d,g];A+=c*q*[d,h];d+=a+c*q>0;j=(j<L(r)-1)*-~j;i+=j<1
print A,D

```

Try it online!

Takes input as a list of strings representing the rows.

The basic approach involves iterating over every square of the grid in left-to-right and top-to-bottom order. The counter `d` is incremented when a word can be made either across or down starting from the current square.

**Some other notes**

* `A` and `D` keep track of the lists of "across" words and "down" words respectively
* To determine whether a square contains a space or a letter, the character gets compared to the `!` character (smaller means a space, larger means it's a letter)
* When a word gets added to one of the lists, `.split()[0]` is called on the remaining portion of the row/column to get the entire word, which ends at the next space character

# Answer
> 2 votes
# perl -M5.010, 348 bytes

```
@a=map{[s/ /0/gr=~/./g,0]}<>;push@a,[(0)x@{$a[0]}];for$y(0..$#a-1){for$x(0..$#{$a[0]}-1){if($a[$y][$x]){$h=$a[$y][$x+1]&&!$a[$y][$x-1];$v=$a[$y+1][$x]&&!$a[$y-1][$x];$c++if$h||$v;if($h){print" $c. ";$i=$x;print$a[$y][$i-1]while$a[$y][$i++]}push@v,[$c,$y,$x]if$v}}}say;for(@v){($c,$y,$x)=@$_;print" $c. ";$i=$y;print$a[$i-1][$x]while$a[$i++][$x]}say

```

Try it online!

Requires the input to be a proper rectangle, that is, shorter lines should be padded with spaces.

# Answer
> 1 votes
# Jelly, 49 bytes

```
Ȧ€Œg⁸ṁȦƇḊƇZ€ḢḢ,Ɗ€)ẎṢ
n⁶a⁸ŒĖṁ⁸Ç,ZÇ$ƊµẎZḢQṢiⱮⱮⱮȯ"""

```

A monadic Link which accepts a (rectangular) list of lists of characters which yields a list of lists of pairs of numbers and lists of characters
...i.e. `[across, down]` where each of `across` and `down` are lists of `[clueNumber, answerWord]`.

**Try it online!** (The footer splits at newlines, calls the Link and formats the result like the question examples.)

### How?

We find all the 2+ letter horizontally written words along with the (2d) index of their first letter in the input matrix for each of the input matrix and its transpose, then sort these (by those indices), and look up each of these starting-indices in a list of the unique starting-indices for the combined results to find the clue-numbers.

```
Ȧ€Œg⁸ṁȦƇḊƇZ€ḢḢ,Ɗ€)ẎṢ - helper Link: list of lists of pairs of 2-d indices and their
                                    characters (or 0s where spaces were)
                 )   - for each row:
Ȧ€                   -   for each pair: any and all? (0 if it contains a 0 (i.e. character was a space))
  Œg                 -   group runs of equal elements
    ⁸ṁ               -   mould like the input
       Ƈ             -   filter keep those for which:
      Ȧ              -     any and all? - i.e. throw away "words" of 0s
         Ƈ           -   filter keep those for which:
        Ḋ            -     dequeue - i.e. throw away words of length 1
          Z€         -   transpose each
                €    -   for each:
               Ɗ     -     last three links as a monad - f(X=that):
            Ḣ        -       head (modifies X too)
             Ḣ       -       head (modifies X too)
              ,      -       pair with (the modified X)
                  Ẏ  - tighten
                   Ṣ - sort

n⁶a⁸ŒĖṁ⁸Ç,ZÇ$ƊµẎZḢQṢiⱮⱮⱮȯ""" - Link: list of lists of characters (C)
 ⁶                           - space character
n                            - (C) not equal (space)? (vectorises)
  a⁸                         - logical AND (C) (vectorises) -> C but with 0s not spaces
    ŒĖ                       - multi-dimensional enumerate -> [[[1,1],'A'],...,[[n,m],'Z']]
      ṁ⁸                     - mould like C
             Ɗ               - last three links as a monad - f(X=that):
        Ç                    -   call the helper Link with X
            $                -   last two links as a monad:
          Z                  -     transpose X
           Ç                 -     call the helper Link with that
         ,                   -   pair these together
              µ              - start a new monadic chain - f(V=that):
               Ẏ             - tighten V
                Z            - transpose
                 Ḣ           - head -> all word-start indices
                  Q          - deduplicate
                   Ṣ         - sort
                     ⱮⱮⱮ     - 3-deep map across v in V with:
                    i        -   first 1-based index of v or 0 if not found
                         """ - zip across, 3-deep with:
                        ȯ    -   logical OR (V) -> replace the 0s with the words from V

```

# Answer
> 1 votes
# JavaScript (ES6), 179 bytes

Takes input as a matrix of characters. Returns a pair of objects.

```
m=>m.map(F=(r,y)=>r.map((c,x)=>i+=1/c?0:(g=(d,s=c,Y=y)=>!(C=m[Y+=d]&&m[Y][x+=!d])|C<F?s[1]&&!!(o[d][i]=s):g(d,s+C,Y),!y||m[y-1][x]<F?g(1):0)|(!x|r[x-1]<F&&g(0))),i=1,o=[{},{}])&&o

```

Try it online!

---
Tags: code-golf, crossword
---