title: Love calculation

text:
# Question
Title: Love calculation
As a kid my sister showed me this little love calculation to see how much chance you have of getting in a successful relationship with your crush. All you need is 2 names and a piece of paper.

* John
* Jane

Then, you separate these names with the word **Loves**. You can either write this on one line or on new lines.

> John
> Loves
> Jane

Then the calculating begins. You start off by counting how many times a character occurs from left to right and in case you use new lines also from top to bottom. Each character is counted once, So after counting the **J** of John you don't have to count them again when you start with Jane. The result of this example will be as follows:

> J: 2 (\[J\]ohn | \[J\]ane)
> O: 2 (J\[o\]hn | L\[o\]ves)
> H: 1 (Jo\[h\]n)
> N: 2 (Joh\[n\] | Ja\[n\]e)
> \__
> L: 1 (\[L\]oves)
> O: **skipped**
> V: 1 (Lo\[v\]es)
> E: 2 (Lov\[e\]s | Jan\[e\])
> S: 1 (Love\[s\])
> \__
> J: **skipped**
> A: 1 (J\[a\]ne)
> N: **skipped**
> E: **skipped**
> \__
> Final result: 2 2 1 2 1 1 2 1 1

The next step will be adding the digits working from the outside to the middle.

> **2** 2 1 2 1 1 2 1 **1** (2+1=3)
> 2 **2** 1 2 1 1 2 **1** 1 (2+1=3)
> 2 2 **1** 2 1 1 **2** 1 1 (1+2=3)
> 2 2 1 **2** 1 **1** 2 1 1 (2+1=3)
> 2 2 1 2 **1** 1 2 1 1 (1)
> \__
> Result: 3 3 3 3 1

You will keep doing this until you have an integer left less or equal to 100.

> **3** *3* 3 *3* **1**
> **4** *6* **3**
> **76%**

It can happen that the sum of 2 digits becomes ≥ 10, in this case the number will be split in 2 on the next row.
Example:

> **5** 3 1 2 5 4 1 **8**
> 13 (Will be used as 1 3)
> 1 3 4 5 7
> 8 8 4 (8+4=12 used as 1 2)
> 1 2 8
> 92%

### Requirements

* Your program should be able to accept any name with reasonable length (100 characters)
* \[A..Z, a..z\] characters are allowed.
* Case insensitive so A == a

### Free for you to decide

* How to handle special characters (Ö, è, etc.)
* Include last names yes or no, spaces will be ignored
* Any language is allowed.

Winner will be determined by votes on the 28th 14th of February.

Happy coding

P.s. This is the first time I put something up here, if there is any way to improve it feel free to let me know =3

**Edit:** Changed end date to valentines day, thought that would be more appropriate for this challenge :)

# Answer
# Sclipting

```
글⓵닆뭶뉗밃變充梴⓶壹꺃뭩꾠⓶꺐合合替虛終梴⓷縮⓶終併❶뉀大套鈮⓶充銻⓷加⓶鈮⓶終併❶뉀大終깐

```

Expects the input as two space-separated words (e.g. `John Jane`). It’s case-insensitive, but supports only characters that are not special regex characters (so don’t use `(` or `*` in your name!). It also expects only two words, so if your love interest is “Mary Jane”, you have to put `MaryJane` in one word; otherwise it will evaluate "YourName loves Mary loves Jane".

## Explanation

The hardest part was to handle the case of odd number of digits: you have to leave the middle digit alone instead of adding it with itself. I think my solution is interesting.

```
글⓵닆뭶뉗밃變 | replace space with "loves"
充 | while non-empty...
    梴 | get length of string
    ⓶壹 | get first character of string (let’s say it’s “c”)
    꺃뭩꾠⓶꺐合合 | construct the regex “(?i:c)”
    替虛終 | replace all matches with empty string
    梴 | get new length of that
    ⓷縮 | subtract the two to get a number
    ⓶ | move string to front
終 | end while
併 | Put all the numbers accrued on the stack into a single string
❶뉀大 | > 100
套 | while true...
    鈮⓶ | chop off the first digit
    充 | while non-empty... (false if that digit was the only one!)
        銻⓷加 | chop off last digit and add them
        ⓶鈮⓶ | chop off the first digit again
                 (returns the empty string if the string is empty!)
    終 | end while
    併 | Put all the numbers (± an empty string ;-) ) on the stack into a single string
    ❶뉀大 | > 100
終 | end while
깐 | add "%"

```

When you’re left with something ≤ 100, the loop will just end, the answer will be on the stack and therefore output.
> 35 votes

# Answer
# Funciton

This program expects the input separated by a space (e.g. `John Jane`). It is case-insensitive **for characters A-Z/a-z;** for any other Unicode character, it will “confuse” two characters that are equal when or’ed with 32 (e.g. `Ā` and `Ġ`, or `?` and `_`). Furthermore, I have no idea what this program will do if the input contains a NUL (`\0`) character, so don’t use that :)

Also, since StackExchange adds too much line spacing, **here is the raw text on pastebin.** Alternatively, run the following code in your browser’s JavaScript console to fix it right here: `$('pre').css('line-height',1)`

```
                               ╓───╖ ╓───╖ ╓───╖ ╓───╖ ╓───╖ ╓───╖
                               ║ Ḷ ║┌╢ Ọ ╟┐║ Ṿ ║ ║ Ẹ ║┌╢ Ṛ ╟┐║ Ṣ ╟┐
                               ╙─┬─╜│╙───╜│╙─┬─╜ ╙─┬─╜│╙─┬─╜│╙─┬─╜│
                                 │  │     │  │     │  │  │  │  │  │
                                 │  │     │  │     │  │  │  │  │  │
                                 │  │     │  │     │  │  │  │  │  │
                                 │  │     │  │     │  │  │  │  │  └───────────┐
                                 │  │     │  │     │  │  │  │  └─────────────┐│
                         ┌───────┘  │     │  │     │  │  │  └───────────────┐││
                         │┌─────────┘     │  │     │  │  └─────────────────┐│││
                         ││┌──────────────┘  │     │  └───────────────────┐││││
                         │││     ┌───────────┘     └──────────────────┐   │││││
                         │││ ┌───┴───┐  ┌─────────────────────────────┴─┐ │││││
                         │││ │ ╔═══╗ │  │                               │ ││││└─────────┐
                         │││ │ ║ 2 ║ │  │     ┌───┐   ┌───┐             │ │││└─────────┐│
                         │││ │ ║ 1 ║ │  │    ┌┴┐  │  ┌┴┐  │             │ ││└─────────┐││
                         │││ │ ║ 1 ║ │  │    └┬┘  │  └┬┘  │             │ │└─────────┐│││
┌────────────────────────┘││ │ ║ 1 ║ │  │   ┌─┴─╖ │ ┌─┴─╖ │     ┌───╖   │ └─────────┐││││
│┌────────────────────────┘│ │ ║ 0 ║ │  │   │ ♯ ║ │ │ ♯ ║ ├─────┤ ℓ ╟───┴─┐         │││││
││┌────────────────────────┘ │ ║ 6 ║ │  │   ╘═╤═╝ │ ╘═╤═╝ │     ╘═══╝   ┌─┴─╖       │││││
│││                    ┌─────┘ ║ 3 ║ │  │    ┌┴┐  │  ┌┴┐  └─────────────┤ · ╟──────┐│││││
│││┌───────────────────┴┐┌───╖ ║ 3 ║ │  │    └┬┘  │  └┬┘                ╘═╤═╝      ││││││
││││                   ┌┴┤ = ╟─╢ 3 ║ │  │ ┌───┘   └───┴─────┐         ┌───┴───┐    ││││││
││││      ╔════╗ ┌───╖ │ ╘═╤═╝ ║ 1 ║ │  │ │ ╔═══╗         ┌─┴─╖       │ ╔═══╗ │    ││││││
││││      ║ 37 ╟─┤ ‼ ╟─┘ ┌─┘   ║ 9 ║ │  │ │ ║ 1 ║ ┌───────┤ · ╟─┐     │ ║ 0 ║ │    ││││││
││││      ╚════╝ ╘═╤═╝  ┌┴┐    ║ 6 ║ │  │ │ ╚═╤═╝ │       ╘═╤═╝ ├─────┘ ╚═╤═╝ │    ││││││
││││ ┌───╖ ┌───╖ ┌─┴─╖  └┬┘    ║ 3 ║ │  │ │ ┌─┴─╖ │ ╔═══╗ ┌─┴─╖ │ ╔═══╗ ┌─┴─╖ │    ││││││
│││└─┤ Ẹ ╟─┤ Ṿ ╟─┤ ? ╟───┤     ║ 3 ║ │  │ └─┤ ʃ ╟─┘ ║ 1 ╟─┤ ʃ ╟─┘ ║ 1 ╟─┤ ʃ ╟─┘    ││││││
│││  ╘═══╝ ╘═══╝ ╘═╤═╝  ┌┴┐    ║ 7 ║ │  │   ╘═╤═╝   ╚═══╝ ╘═╤═╝   ╚═══╝ ╘═╤═╝      ││││││
│││                │    └┬┘    ╚═══╝ │  │     │  ┌──────────┘             └──────┐ ││││││
│││              ╔═══╗ ┌─┴─╖ ┌───╖   │  │     │  │ ┌─────────╖ ┌───╖ ┌─────────╖ │ ││││││
│││              ║ 3 ╟─┤ > ╟─┤ ℓ ╟───┘  │     │  └─┤ str→int ╟─┤ + ╟─┤ str→int ╟─┘ ││││││
│││              ╚═══╝ ╘═══╝ ╘═══╝      │     │    ╘═════════╝ ╘═╤═╝ ╘═════════╝   ││││││
││└───────────────────────────────────┐ │     │             ┌────┴────╖            ││││││
│└───────────────────────────────┐    │ │     │             │ int→str ║            ││││││
│          ╔═══╗                 │    │ │     │ ┌───╖ ┌───╖ ╘════╤════╝            ││││││
│          ║ 0 ║                 │    │ │     └─┤ Ẹ ╟─┤ ‼ ╟──────┘                 ││││││
│          ╚═╤═╝                 │    │ │       ╘═══╝ ╘═╤═╝   ┌────────────────────┘│││││
│    ╔═══╗ ┌─┴─╖                 │    │ │             ┌─┴─╖ ┌─┴─╖ ╔═══╗             │││││
│    ║ 1 ╟─┤ ʃ ╟─────────────────┴┐   │ └─────────────┤ ? ╟─┤ ≤ ║ ║ 2 ║             │││││
│    ╚═══╝ ╘═╤═╝                  │   │               ╘═╤═╝ ╘═╤═╝ ╚═╤═╝             │││││
│          ┌─┴─╖                  │   │                 │     └─────┘               │││││
│        ┌─┤ Ṣ ╟──────────────────┴┐  │    ╔═══╗   ┌────────────────────────────────┘││││
│        │ ╘═╤═╝                   │  │    ║   ║   │  ┌──────────────────────────────┘│││
│        │ ┌─┴─╖                   │  │    ╚═╤═╝   │  │    ┌──────────────────────────┘││
│        └─┤ · ╟─────────────┐     │  │    ┌─┴─╖   │┌─┴─╖┌─┴─╖                         ││
│          ╘═╤═╝             │     │  │    │ Ḷ ║   └┤ · ╟┤ · ╟┐                        ││
│      ┌─────┴───╖         ┌─┴─╖ ┌─┴─╖│    ╘═╤═╝    ╘═╤═╝╘═╤═╝│                        ││
│      │ int→str ║ ┌───────┤ · ╟─┤ · ╟┴┐     │      ┌─┴─╖  │  │                        ││
│      ╘═════╤═══╝ │       ╘═╤═╝ ╘═╤═╝ │           ┌┤ · ╟──┘  │                        ││
│            │   ┌─┴─╖ ┌───╖ │     │   │         ┌─┘╘═╤═╝   ┌─┴─╖                      ││
│            │   │ ‼ ╟─┤ Ọ ╟─┘     │   │         │ ┌──┴─────┤ · ╟───────┐              ││
│            │   ╘═╤═╝ ╘═╤═╝       │   │         │ │ ╔════╗ ╘═╤═╝ ╔═══╗ │              ││
│            └─────┘     │         │   │         │ │ ║ 21 ║   │   ║ 2 ║ │              ││
│                ┌───╖ ┌─┴─╖       │   │  ┌──────┘ │ ╚═══╤╝   │   ║ 0 ║ │              ││
│            ┌───┤ Ṿ ╟─┤ ? ╟───────┘   │  │┌───╖ ┌─┴─╖ ┌─┴──╖ │   ║ 9 ║ │              ││
│            │   ╘═══╝ ╘═╤═╝           │ ┌┴┤ ♯ ╟─┤ Ṛ ╟─┤ >> ║ │   ║ 7 ║ │              ││
│            │           │             │ │ ╘═══╝ ╘═╤═╝ ╘══╤═╝ │   ║ 1 ║ │              ││
│            └─────────┐   ┌───────────┘ │ ╔═══╗ ┌─┴─╖    ├───┴─┬─╢ 5 ║ │              ││
└───────────────────┐  └───┘             │ ║ 0 ╟─┤ ? ╟────┘     │ ║ 1 ║ │              ││
╔════╗              │                    │ ╚═══╝ ╘═╤═╝   ┌──────┤ ╚═══╝ │              ││
║ 21 ║              │                    │       ┌─┴─╖ ┌─┴─╖ ╔══╧══╗    │              ││
╚═╤══╝              │                    └───────┤ ? ╟─┤ ≠ ║ ║ −33 ║    │              ││
┌─┴─╖ ┌────╖        │                            ╘═╤═╝ ╘═╤═╝ ╚══╤══╝   ┌┴┐             ││
│ × ╟─┤ >> ╟────────┴────────────┐                 │     └──────┤      └┬┘             ││
╘═╤═╝ ╘═╤══╝ ┌───╖   ╔═════════╗ │                              └───────┘              ││
┌─┴─╖   └────┤ ‼ ╟───╢ 2224424 ║ │                ┌────────────────────────────────────┘│
│ ♯ ║        ╘═╤═╝   ║ 4396520 ║ │                │    ┌────────────────────────────────┘
╘═╤═╝        ┌─┴─╖   ║ 1237351 ║ │                │    │    ┌─────────────────────┐
  └──────────┤ · ╟─┐ ║ 2814700 ║ │                │  ┌─┴─╖  │     ┌─────┐         │
             ╘═╤═╝ │ ╚═════════╝ │              ┌─┴──┤ · ╟──┤     │    ┌┴┐        │
 ╔═══╗ ┌───╖ ┌─┴─╖ │   ╔════╗    │            ┌─┴─╖  ╘═╤═╝┌─┴─╖   │    └┬┘        │
 ║ 0 ╟─┤ Ọ ╟─┤ ‼ ║ │   ║ 32 ║    │   ┌────────┤ · ╟────┴──┤ Ṛ ╟───┤   ┌─┴─╖       │
 ╚═══╝ ╘═╤═╝ ╘═╤═╝ │   ╚═╤══╝    │   │        ╘═╤═╝       ╘═╤═╝   │   │ ♯ ║       │
         │   ┌─┴─╖ ├─┐ ┌─┴─╖     │ ┌─┴─╖      ┌─┴─╖       ╔═╧═╗   │   ╘═╤═╝       │
           ┌─┤ ʃ ╟─┘ └─┤ ʘ ║     │┌┤ · ╟──────┤ · ╟───┐   ║ 1 ║   │    ┌┴┐        │
           │ ╘═╤═╝     ╘═╤═╝     ││╘═╤═╝      ╘═╤═╝   │   ╚═══╝   │    └┬┘        │
           │ ╔═╧═╗       ├───────┘│  │       ┌──┴─╖ ┌─┴─╖ ┌───╖ ┌─┴─╖ ┌─┴─╖ ╔═══╗ │
           │ ║ 0 ║       │        │  │       │ >> ╟─┤ Ṣ ╟─┤ ‼ ╟─┤ · ╟─┤ ʃ ╟─╢ 0 ║ │
           │ ╚═══╝       │        │  │       ╘══╤═╝ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ ╚═══╝ │
           └─────────────┘        │  │ ╔════╗ ┌─┴─╖ ┌─┴─╖ ┌─┴─╖ ┌─┘     ├─────────┘
                                  │  │ ║ 21 ╟─┤ × ╟─┤ · ╟─┤ · ╟─┴─┐     │
                                  │  │ ╚════╝ ╘═══╝ ╘═╤═╝ ╘═╤═╝   │     │
                                  │  └────────────────┘   ┌─┴─╖   │     │
                                  │                   ┌───┤ ? ╟───┴┐    │
                                  │                   │   ╘═╤═╝    │    │
                                  │           ┌───╖ ┌─┴─╖   │    ┌─┴─╖  │
                                  └───────────┤ ♯ ╟─┤ · ╟─┐   ┌──┤ ? ╟─ │
                                              ╘═══╝ ╘═╤═╝ └───┘  ╘═╤═╝  │
                                                      │          ╔═╧═╗  │
                                                      │          ║ 0 ║  │
                                                      │          ╚═══╝  │
                                                      └─────────────────┘

```

## Quick explanation

* The program just takes STDIN and calls  with it.
* finds the first space in the string, replaces it with `loves` and passes the result to .
* repeatedly takes the first character from the input string, calls  with it and concatenates the numbers of occurrences onto a result string. When the input string is empty, it calls  with the result string.
* repeatedly calls  until it gets a result that is either equal to `"100"` or has length less than 3. (`100` can actually occur: consider the input `lovvvv eeeeeess`.) When it does, it adds `"%"` and returns that.
* computes one complete iteration of the love-computation algorithm; i.e., it takes a string of digits and returns the next string of digits.
* takes a *haystack* and a *needle* and finds the index of the first occurrence of *needle* in *haystack* using the faux case-insensitivity criterion (`or 32`).
* takes a *haystack* and a *needle* and repeatedly applies  to remove all instances of the *needle*. It returns the final result after all the removals as well as the number of removals made.
> 28 votes

# Answer
# Ruby

```
     f=IO.         read(
   __FILE__)     .gsub(/[^
 \s]/x,?#);s=   $**'loves';s
.upcase!;i=1;a =s.chars.uniq.
map{|c|s.count(c)};loop{b='';
b<<"#{a.shift.to_i+a.pop.to_i
 }"while(a.any?);d=b.to_i;a=
   b.chars;d<101&&abort(d>
     50?f:f.gsub(/^.*/){
       |s|i=13+i%3;s[\
         i...i]=040.
           chr*3;s
             })}
              V

```

Prints a heart if the chance of a relation is over 50%

```
$ ruby ♥.rb sharon john
     #####         #####
   #########     #########
 ############   ############
############## ##############
#############################
#############################
 ###########################
   #######################
     ###################
       ###############
         ###########
           #######
             ###
              #

```

And prints a broken heart if chances are below 50% :(

```
$ ruby ♥.rb sharon epidemian
     #####            #####
   #########        #########
 ############      ############
##############    ##############
###############   ##############
#############   ################
 #############   ##############
   ############   ###########
     ########   ###########
       #######   ########
         ######   #####
           ##   #####
             #   ##
              #

```

Frigging John...

Anyways, it's case-insensitive and supports polygamous queries (e.g. `ruby ♥.rb Alice Bob Carol Dave`).
> 28 votes

# Answer
# APL, 80

```
{{n←⍎∊⍕¨(⍵[⌈m]/⍨m≠⌊m),⍨+/(⌊m←2÷⍨≢⍵)↑[1]⍵,⍪⌽⍵⋄n≤100:n⋄∇⍎¨⍕n}∪⍦32|⎕UCS⍺,'Loves',⍵}

```

Because ~~love is love~~ is (even when it's not)

Obligatory ♥-shaped version:

```
    {f←{m←  2÷⍨≢⍵
  n←+/(⌊m)↑[1]⍵,⍪⌽⍵
n←⍎∊⍕¨n,(⍵[⌈m]/⍨m≠⌊m)
n≤100:n⋄∇⍎¨⍕n}⋄u←⎕UCS
   s←u⍺,'Loves',⍵
       f∪⍦32|s
          }

```

The golfed version gives me somewhat erratic behaviour, because of a bug with `∪⍦` that I'm investigating with NARS's developers:

```
      'John'{{n←⍎∊⍕¨(⍵[⌈m]/⍨m≠⌊m),⍨+/(⌊m←2÷⍨≢⍵)↑[1]⍵,⍪⌽⍵⋄n≤100:n⋄∇⍎¨⍕n}∪⍦32|⎕UCS⍺,'Loves',⍵}'Jane'
VALUE ERROR

```

But I was able to run it piecewise and get the correct result:

```
      'John'{∪⍦32|⎕UCS⍺,'Loves',⍵}'Jane'
2 2 1 2 1 1 2 1 1
      {n←⍎∊⍕¨(⍵[⌈m]/⍨m≠⌊m),⍨+/(⌊m←2÷⍨≢⍵)↑[1]⍵,⍪⌽⍵⋄n≤100:n⋄∇⍎¨⍕n}2 2 1 2 1 1 2 1 1
76

```
> 11 votes

# Answer
# Javascript

Probably could be cleaner, but it works. **Verbose example**

```
function z(e) {
    for (var t = 0, c = '', n = e.length - 1; n >= t; n--, t++) {
        c += n != t ? +e[t] + (+e[n]) : +e[t];
    }
    return c
}
for (var s = prompt("Name 1").toLowerCase() + "loves" + prompt("Name 2").toLowerCase(),b = '', r; s.length > 0;) {
    r = new RegExp(s[0], "g");
    b+=s.match(r).length;
    s = s.replace(r, "")
}
for (; b.length > 2; b = z(b)) {}
console.log("Chances of being in love are: " + b + "%")

```
> 8 votes

# Answer
# Python

Well, I thought it was a ...

```
a=filter(str.isalpha,raw_input()+"loves"+raw_input()).lower();a=[x[1]for x in sorted(set(zip(a,map(str.count,[a]*len(a),a))),key=lambda(x,y):a.index(x))]
while reduce(lambda x,y:x*10+y,a)>100:a=reduce(list.__add__,map(lambda x: x<10 and[x]or map(int,str(x)),[a[n]+a[-n-1]for n in range(len(a)/2)]+(len(a)%2 and[a[len(a)/2]]or[])))
print str(reduce(lambda x,y:x*10+y,a))+"%"

```

Ungolfed:

```
a = filter(str.isalpha,
           raw_input() + "loves" + raw_input()).lower()

a = [x[1] for x in sorted(set(zip(a,
                                  map(str.count, [a] * len(a), a))),
                          key=lambda (x, y): a.index(x))]

while reduce(lambda x, y: x * 10 + y, a) > 100:
    a = reduce(list.__add__,
               map(lambda x: x < 10 and [x] or map(int, str(x)),
                   [a[n] + a[-n - 1] for n in range(len(a) / 2)] + (len(a) % 2 and [a[len(a) / 2]] or [])))

print str(reduce(lambda x, y: x * 10 + y, a)) + "%"

```
> 7 votes

# Answer
PHP

```
<?php

$name1 = $argv[1];
$name2 = $argv[2];

echo "So you think {$name1} and {$name2} have any chance? Let's see.\nCalculating if \"{$name1} Loves {$name2}\"\n";

//prepare it, clean it, mince it, knead it
$chances = implode('', array_count_values(str_split(preg_replace('/[^a-z]/', '', strtolower($name1.'loves'.$name2)))));
while(($l = strlen($chances))>2 and $chances !== '100'){
    $time = time();
    $l2 = intval($l/2);
    $i =0;
    $t = '';
    while($i<$l2){
        $t.=substr($chances, $i, 1) + substr($chances, -$i-1, 1);
        $i++;
    }
    if($l%2){
        $t.=$chances[$l2];
    }
    echo '.';
    $chances = $t;
    while(time()==$time){}
}

echo "\nTheir chances in love are {$chances}%\n";
$chances = intval($chances);
if ($chances === 100){
    echo "Great!!\n";
}elseif($chances > 50){
    echo "Good for you :) !!\n";
}elseif($chances > 10){
    echo "Well, it's something.\n";
}else{
    echo "Ummm.... sorry.... :(\n";
}

```

sample result

```
$ php loves.php John Jane
So you think John and Jane have any chance? Let's see.
Calculating if "John Loves Jane"
...
Their chances in love are 76%
Good for you :) !!

```
> 5 votes

# Answer
## GolfScript

Obligatory code golf answer in GolfScript:

```
' '/'loves'*{65- 32%65+}%''+:x.|{{=}+x\,,}%{''\{)\(@+@\+\.(;}do 0+{+}*+{[]+''+~}%.,((}do{''+}%''+

```

Accepts input as space-separated names e.g.

```
echo 'John Jane' | ruby golfscript.rb love.gs
-> 76

```
> 4 votes

# Answer
## C#

```
using System;
using System.Collections.Generic;
using System.Linq;

namespace LovesMeWhat
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 2) throw new ArgumentException("Ahem, you're doing it wrong.");

            Func<IEnumerable<Int32>, String> fn = null;
            fn = new Func<IEnumerable<Int32>, String> (input => {
                var q = input.SelectMany(i => i.ToString().Select(c => c - '0')).ToArray();

                if (q.Length <= 2) return String.Join("", q);

                IList<Int32> next = new List<Int32>();
                for (int i = 0, j = q.Length - 1; i <= j; ++i, --j)
                {
                    next.Add(i == j ? q[i] : q[i] + q[j]);
                }
                return fn(next);
            });

            Console.Write(fn(String.Concat(args[0], "LOVES", args[1]).ToUpperInvariant().GroupBy(g => g).Select(g => g.Count())));
            Console.Write("%");
            Console.ReadKey(true);
        }
    }
}

```
> 4 votes

# Answer
# Haskell

My version is pretty long, it's because I decided to focus on readability, I thought it would be interesting to formalize your algorithm in code. I aggregate character counts in a *left fold*, it basically snowballs them together and order is in order of their occurrence in the string. I also managed to replace the part of algorithm that would normally require array indexing with list *bending*. It turns out your algorithm basically involves folding list of numbers in half and adding aligned numbers together. There two cases for bending, even lists split in the middle nicely, odd lists bend around a center element and that element doesn't participate in addition. *Fission* is taking the list and splitting up numbers that are no longer single digits, like *\>= 10*. I had to write my own *unfoldl*, I'm not sure if it's actually an *unfoldl*, but it seems to do what i need. Enjoy.

```
import qualified Data.Char as Char
import qualified System.Environment as Env

-- | Takes a seed value and builds a list using a function starting
--   from the last element
unfoldl :: (t -> Maybe (t, a)) -> t -> [a]
unfoldl f b  =
  case f b of
   Just (new_b, a) -> (unfoldl f new_b) ++ [a]
   Nothing -> []

-- | Builds a list from integer digits
number_to_digits :: Integral a => a -> [a]
number_to_digits n = unfoldl (\x -> if x == 0
                                     then Nothing
                                     else Just (div x 10, mod x 10)) n

-- | Builds a number from a list of digits
digits_to_number :: Integral t => [t] -> t
digits_to_number ds = number
  where (number, _) = foldr (\d (n, p) -> (n+d*10^p, p+1)) (0,0) ds

-- | Bends a list at n and returns a tuple containing both parts
--   aligned at the bend
bend_at :: Int -> [a] -> ([a], [a])
bend_at n xs = let
                 (left, right) = splitAt n xs
                 in ((reverse left), right)

-- | Takes a list and bends it around a pivot at n, returns a tuple containing
--   left fold and right fold aligned at the bend and a pivot element in between
bend_pivoted_at :: Int -> [t] -> ([t], t, [t])
bend_pivoted_at n xs
  | n > 1 = let
              (left, pivot:right) = splitAt (n-1) xs
              in ((reverse left), pivot, right)

-- | Split elements of a list that satisfy a predicate using a fission function
fission_by :: (a -> Bool) -> (a -> [a]) -> [a] -> [a]
fission_by _ _ [] = []
fission_by p f (x:xs)
  | (p x) = (f x) ++ (fission_by p f xs)
  | otherwise = x : (fission_by p f xs)

-- | Bend list in the middle and zip resulting folds with a combining function.
--   Automatically uses pivot bend for odd lists and normal bend for even lists
--   to align ends precisely one to one
fold_in_half :: (b -> b -> b) -> [b] -> [b]
fold_in_half f xs
  | odd l = let
              middle = (l-1) `div` 2 + 1
              (left, pivot, right) = bend_pivoted_at middle xs
              in pivot:(zipWith f left right)
  | otherwise = let
                  middle = l `div` 2
                  (left, right) = bend_at middle xs
                  in zipWith f left right
  where
    l = length xs

-- | Takes a list of character counts ordered by their first occurrence
--   and keeps folding it in half with addition as combining function
--   until digits in a list form into any number less or equal to 100
--   and returns that number
foldup :: Integral a => [a] -> a
foldup xs
  | n > 100 = foldup $ fission $ reverse $ (fold_in_half (+) xs)
  | otherwise = n
  where
    n = (digits_to_number xs)
    fission = fission_by (>= 10) number_to_digits

-- | Accumulate counts of keys in an associative array
count_update :: (Eq a, Integral t) => [(a, t)] -> a -> [(a, t)]
count_update [] x = [(x,1)]
count_update (p:ps) a
  | a == b = (b,c+1) : ps
  | otherwise = p : (count_update ps a)
  where
    (b,c) = p

-- | Takes a string and produces a list of character counts in order
--   of their first occurrence
ordered_counts :: Integral b => [Char] -> [b]
ordered_counts s = snd $ unzip $ foldl count_any_alpha [] s
  where
    count_any_alpha m c
      | Char.isAlpha c = count_update m (Char.toLower c)
      | otherwise = m

-- | Take two names and perform the calculation
love_chances n1 n2 =  foldup $ ordered_counts (n1 ++ " loves " ++ n2)

main = do
   args <- Env.getArgs
   if (null args) || (length args < 2)
     then do
            putStrLn "\nUSAGE:\n"
            putStrLn "Enter two names separated by space\n"
     else let
            n1:n2:_ = args
            in putStrLn $ show (love_chances n1 n2) ++ "%"

```

## Some Results:

"Romeo" "Juliet" 97% - *Empirical testing is important*
"Romeo" "Julier" 88% - *Modern abridged version...*
"Horst Draper" "Jane" 20%
"Horst Draper" "Jane(Horse)" 70% - *There's been a development...*
"Bender Bender Rodriguez" "Fenny Wenchworth" 41% - *Bender Says "Folding is for women!"*
"Philip Fry" "Turanga Leela" 53% - *Well you can see why it took 7 Seasons for them to marry*
**"Maria" "Abraham" - 98%<br>"John" "Jane" 76%**
> 4 votes

# Answer
# Ruby

```
math = lambda do |arr|
  result = []
  while arr.any?
    val = arr.shift + (arr.pop || 0)
    result.push(1) if val >= 10
    result.push(val % 10)
  end
  result.length > 2 ? math.call(result) : result
end
puts math.call(ARGV.join("loves").chars.reduce(Hash.new(0)) { |h, c| h[c.downcase] += 1; h }.values).join

```

Minified:

```
l=->{|a|r=[];while a.any?;v=a.shift+(a.pop||0);r.push(1) if v>=10;r.push(v%10) end;r[2]?l[r]:r}
puts l[ARGV.join("loves").chars.reduce(Hash.new(0)){|h, c| h[c.downcase]+=1;h}.values].join

```

Call it:

```
$ ruby love.rb "John" "Jane"
76

```
> 3 votes

# Answer
# Python 3

A simple solution that uses no modules. I/O is pretty enough.

I used error catching as a backup for when the second iterator is out of bounds; if it catches Python's index error, it assumes 1. Weird, but it works.

```
names = [input("Name 1: ").lower(), "loves", input("Name 2: ").lower()]
checkedLetters = []

def mirrorAdd(n):
    n = [i for i in str(n)]
    if len(n) % 2:
        n.insert(int(len(n)/2), 0)
    return(int(''.join([str(int(n[i]) + int(n[len(n)-i-1])) for i in range(int(len(n)/2))])))

cn = ""

positions = [0, 0]
for i in [0, 1, 2]:
    checkAgainst = [0, 1, 2]
    del checkAgainst[i]
    positions[0] = 0
    while positions[0] < len(names[i]):
        if not names[i][positions[0]] in checkedLetters:
            try:
                if names[i][positions[0]] in [names[checkAgainst[0]][positions[1]], names[checkAgainst[1]][positions[1]]]:
                    positions[1] += 1
                    cn = int(str(cn) + "2")
                else:
                    cn = int(str(cn) + "1")
            except:
                cn = int(str(cn) + "1")
            checkedLetters.append(names[i][positions[0]])
        positions[0] += 1

print("\n" + str(cn))

while cn > 100:
    cn = mirrorAdd(cn)
    print(cn)

print("\n" + str(cn) + "%")

```

Here's a sample run:

```
Name 1: John
Name 2: Jane

221211211
33331
463
76

76%

```
> 2 votes

# Answer
**Python 3**

This will take two names as input. strip extra spaces and then calculate love. Check out Input output for more details.

```
s=(input()+'Loves'+input()).strip().lower()
a,b=[],[]
for i in s:
    if i not in a:
        a.append(i)
        b.append(s.count(i))
z=int(''.join(str(i) for i in b))
while z>100:
    x=len(b)
    t=[]
    for i in range(x//2):
        n=b[-i-1]+b[i]
        y=n%10
        n//=10
        if n:t.append(n)
        t.append(y)
    if x%2:t.append(b[x//2])
    b=t
    z=int(''.join(str(i) for i in b))
print("%d%%"%z)

```

input:

```
Maria
Abraham

```

output:

```
98%

```

Or, try this one ;)

input:

```
Wasi Mohammed Abdullah
code golf

```

output:

```
99%

```
> 2 votes

# Answer
## Java

> It can happen that the sum of 2 digits becomes greater than 10, in this case the number will be split in 2 on the next row.

What if the number is equal to 10? I just added 1 and 0, is that correct?

I decided to ignore case.

```
public class LoveCalculation {
    public static void main(String[] args) {
        String chars = args[0].toLowerCase() + "loves" + args[1].toLowerCase();
        ArrayList<Integer> charCount = new ArrayList<Integer>();
        HashSet<Character> map = new HashSet<Character>();
        for(char c: chars.toCharArray()){
            if(Pattern.matches("[a-z]", "" + c) && map.add(c)){
                int index = -1, count = 0;
                while((index = chars.indexOf(c, index + 1)) != -1)
                    count++;
                charCount.add(count);
            }
        }
        while(charCount.size() > 2){
            ArrayList<Integer> numbers = new ArrayList<Integer>();
            for(int i = 0; i < (charCount.size()/2);i++)
                addToArray(charCount.get(i) + charCount.get(charCount.size()-1-i), numbers);
            if(charCount.size() % 2 == 1){
                addToArray(charCount.get(charCount.size()/2), numbers);
            }
            charCount = new ArrayList<Integer>(numbers);
        }
        System.out.println(Arrays.toString(charCount.toArray()).replaceAll("[\\]\\[,\\s]","") + "%");
    }
    public static ArrayList<Integer> addToArray(int number, ArrayList<Integer> numbers){
        LinkedList<Integer> stack = new LinkedList<Integer>();
        while (number > 0) {
            stack.push(number % 10);
            number = number / 10;
        }
        while (!stack.isEmpty())
            numbers.add(stack.pop());
        return numbers;
    }
}

```

input:

```
Maria
Abraham

```

output:

```
98%

```

input:

```
Wasi
codegolf.stackexchange.com

```

output:

```
78%

```
> 2 votes

# Answer
# C

There might be lots of improvement, but this was fun to code.

```
#include <stdio.h>
#include <string.h>
int i, j, k, c, d, r, s = 1, l[2][26];
char a[204], *p, *q;

main(int y, char **z) {
    strcat(a, z[1]);
    strcat(a, "loves");
    strcat(a, z[2]);
    p = a;
    q = a;
    for (; *q != '\0'; q++, p = q, i++) {
        if (*q == 9) {
            i--;
            continue;
        }
        l[0][i] = 1;
        while (*++p != '\0')
            if ((*q | 96) == (*p | 96)&&*p != 9) {
                (l[0][i])++;
                *p = 9;
            }
    }
    for (;;) {
        for (j = 0, k = i - 1; j <= k; j++, k--) {
            d = j == k ? l[r][k] : l[r][j] + l[r][k];
            if (d > 9) {
                l[s][c++] = d % 10;
                l[s][c++] = d / 10;
            } else l[s][c++] = d;
            if (k - j < 2)break;
        }
        i = c;
        if (c < 3) {
            printf("%d", l[s][0]*10 + l[s][1]);
            break;
        }
        c = r;
        r = s;
        s = c;
        c = 0;
    }
}

```

And of course, mandatory golfed version: 496

```
#include <stdio.h>
#include <string.h>
int i,j,k,c,d,r,s=1,l[2][26];char a[204],*p,*q;main(int y,char **z){strcat(a,z[1]);strcat(a,"loves");strcat(a,z[2]);p=q=a;for(;*q!='\0';q++,p=q,i++){if(*q==9){i--;continue;}l[0][i]=1;while(*++p!='\0')if((*q|96)==(*p|96)&&*p!=9){(l[0][i])++;*p=9;}}for(;;){for(j=0,k=i-1;j<=k;j++,k--){d=j==k?l[r][k]:l[r][j]+l[r][k];if(d>9){l[s][c++]=d%10;l[s][c++]=d/10;}else l[s][c++]=d;if(k-j<2)break;}i=c;if(c<3){printf("%d",l[s][0]*10+l[s][1]);break;}c=r;r=s;s=c;c=0;}}

```
> 2 votes

# Answer
# Groovy

Here's the groovy version, with tests.

```
countChars = { res, str -> str ? call(res+str.count(str[0]), str.replace(str[0],'')) : res }
addPairs = { num -> def len = num.length()/2; (1..len).collect { num[it-1].toInteger() + num[-it].toInteger() }.join() + ((len>(int)len) ? num[(int)len] : '') }
reduceToPct = { num -> /*println num;*/ num.length() > 2 ? call( addPairs(num) ) : "$num%" }

println reduceToPct( countChars('', args.join('loves').toLowerCase()) )

assert countChars('', 'johnlovesjane') == '221211211'
assert countChars('', 'asdfasdfateg') == '3222111'
assert addPairs('221211211') == '33331'
assert addPairs('33331') == '463'
assert addPairs('463') == '76'
assert addPairs('53125418') == '13457'
assert addPairs('13457') == '884'
assert addPairs('884') == '128'
assert addPairs('128') == '92'
assert reduceToPct( countChars('','johnlovesjane') ) == '76%'

```

### Explanation:

* "countChars" simply recurses and removes while build a string of digits
* "addPairs" takes one string of digits adding the digits from the outside in \** the "collect..join" does the addition of the digits working outside in and rejoins them as a string \** the "+ (... c\[(int)len\])" throws in the middle digit again when c is an odd length
* "recudeToPct" calls itself adding pairs until it gets down to less than 3 digits

# CodeGolf Groovy, 213 char

Seeing this is we can inline the closures and get it down to this:

```
println({c->l=c.length()/2;m=(int)l;l>1?call((1..m).collect{(c[it-1]as int)+(c[-it]as int)}.join()+((l>m)?c[m]:'')):"$c%"}({r,s->s?call(r+s.count(s[0]),s.replace(s[0],'')):r}('',args.join('loves').toLowerCase())))

```

save it as lovecalc.groovy. run "groovy lovecalc john jane"

### Output:

```
$ groovy lovecalc john jane
76%
$ groovy lovecalc romeo juliet
97%
$ groovy lovecalc mariah abraham
99%
$ groovy lovecalc maria abraham
98%
$ groovy lovecalc al bev
46%
$ groovy lovecalc albert beverly
99%

```
> 2 votes

# Answer
# k, 80

```
{{$[(2=#x)|x~1 0 0;x;[r:((_m:(#x)%2)#x+|x);$[m=_m;r;r,x@_m]]]}/#:'.=x,"loves",y}

```

Here is a run of it:

```
{{$[(2=#x)|x~1 0 0;x;[r:((_m:(#x)%2)#x+|x);$[m=_m;r;r,x@_m]]]}/#:'.=x,"loves",y}["john";"jane"]
7 6

```
> 2 votes

# Answer
## J

Here's a straightforward one in J:

```
r=:({.+{:),$:^:(#>1:)@}:@}.
s=:$:^:(101<10#.])@("."0@(#~' '&~:)@":"1)@r
c=:10#.s@(+/"1@=)@(32|3&u:@([,'Loves',]))
exit echo>c&.>/2}.ARGV

```

It takes the names on the command line, e.g:

```
$ jconsole love.ijs John Jane
76

```
> 2 votes

# Answer
## Java

This takes 2 String parameters on start and prints out the count of each character and the result.

```
import java.util.ArrayList;
import java.util.LinkedHashMap;

public class LUV {
    public static void main(String[] args) {
        String str = args[0].toUpperCase() + "LOVES" + args[1].toUpperCase();
        LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
        for (int i = 0; i < str.length(); i++) {
            if (!map.containsKey(String.valueOf(str.charAt(i)))) {
                map.put(String.valueOf(str.charAt(i)), 1);
            } else {
                map.put(String.valueOf(str.charAt(i)), map.get(String.valueOf(str.charAt(i))).intValue() + 1);
            }
        }
        System.out.println(map.toString());
        System.out.println(addValues(new ArrayList<Integer>(map.values()))+"%");
    }

    private static int addValues(ArrayList<Integer> list) {
        if ((list.size() < 3) || (Integer.parseInt((String.valueOf(list.get(0)) + String.valueOf(list.get(1))) + String.valueOf(list.get(2))) == 100)) {
            return Integer.parseInt((String.valueOf(list.get(0)) + String.valueOf(list.get(1))));
        } else {
            ArrayList<Integer> list2 = new ArrayList<Integer>();
            int size = list.size();
            for (int i = 0; i < size / 2; i++) {
                int temp = list.get(i) + list.get(list.size() -1);
                if (temp > 9) {
                    list2.add(temp/10);
                    list2.add(temp%10);
                } else {
                    list2.add(temp);
                }
                list.remove(list.get(list.size()-1));
            }
            if (list.size() > list2.size()) {
                list2.add(list.get(list.size()-1));
            }
            return addValues(list2);
        }
    }
}

```

Surely not the shortest one (it's Java), but a clear and readable one.

So if you call

```
java -jar LUV.jar JOHN JANE

```

you get the output

```
{J=2, O=2, H=1, N=2, L=1, V=1, E=2, S=1, A=1}
76%

```
> 1 votes

# Answer
**R**

Not going to win any compactness awards, but I had fun anyway:

```
problove<-function(name1,name2, relation='loves') {
sfoo<-tolower( unlist( strsplit(c(name1,relation,name2),'') ) )
startrow <- table(sfoo)[rank(unique(sfoo))]
# check for values > 10 . Not worth hacking an arithmetic approach
startrow <- as.integer(unlist(strsplit(as.character(startrow),'')))
while(length(startrow)>2 ) {
    tmprow<-vector()
    # follow  by tacking on middle element if length is odd
    srlen<-length(startrow)
     halfway<-trunc( (srlen/2))
    tmprow[1: halfway] <- startrow[1:halfway] + rev(startrow[(srlen-halfway+1):srlen])
    if ( srlen%%2) tmprow[halfway+1]<-startrow[halfway+1]
    startrow <- as.integer(unlist(strsplit(as.character(tmprow),'')))
    }
as.numeric(paste(startrow,sep='',collapse=''))
}

```

Tested: valid for 'john'&'jane' and for 'romeo'&'juliet' . per my comment under the question,

```
Rgames> problove('john','jane','hates')
[1] 76
Rgames> problove('romeo','juliet','hates')
[1] 61

```
> 1 votes

---
Tags: popularity-contest
---


title: Password Generator

text:
# Question
Title: Password Generator
Task:
Make a program that generate a 24-digit password.

Rule:

* None of the character can be repeated more than once
* Must include at least one upcase, one locase, one number, five special character.
* The answer which got most votes win.

SPECIAL CHARACTER LIST: \`~!@#$%^&\*()\_+-={}|\[\]\\:";'\<\>?,./ or other

# Answer
# bash

You might need to tune `A-M` by increasing or decreasing the range to meet specs.

```
ls -al ~ | grep -o . | tr -d A-M | sort | uniq | head -n 24 | xargs | sed 's/ //g'

```

E.g:

```
$ ls -al ~ | grep -o . | tr -d A-M | sort | uniq | head -n 24 | xargs | sed 's/ //g'

+-.0123456789:@OPSTU_a

```
> 0 votes

---
Tags: popularity-contest, random
---


# Question
Title: Write a program that says how many times it was ran
Write a program that after running will show how many times it was ran before. You are only allowed to modify the executable itself (the code itself, or compiled version of your code), you cannot modify anything else or create new files.

Example:

```
$ ./yourprogram
0
$ ./yourprogram
1
$ ./yourprogram
2

```

# Answer
Somewhat less trivial example than y'old bash, in C:

```
#include <stdio.h>

int main(int argc,char **argv){
    const char *data="Da best marker in da world 0\0\0\0\0\0\0";
    FILE *f;
    int i;
    char c;
    long int pos;
    printf("%s\n",data+27);
    f=fopen(argv[0],"r+b");
    i=0;
    c=fgetc(f);
    while(!feof(f)){
        if(data[i]==c){
            i++;
            if(i==27)break;
        } else i=0;
        c=fgetc(f);
    }
    if(i!=27)return 1;
    i=0;
    pos=ftell(f);
    c=fgetc(f);
    while(c!='\0'){
        i=10*i+c-'0';
        c=fgetc(f);
    }
    i++; //The increment!
    fseek(f,pos,SEEK_SET);
    fprintf(f,"%d",i);
    fflush(f);
    fclose(f);
    return 0;
}

```
> 2 votes

---
Tags: popularity-contest
---


title: Interpret a circuit diagram

text:
# Question
Title: Interpret a circuit diagram
Your challenge is to interpret a circuit diagram, complete with logic gates.

Logic gates (you don't actually need to know what these do / are to complete this challenge):

* and gate: `a`
* or gate: `o`
* nand gate: `A`
* nor gate: `O`
* xor gate: `x`
* xnor gate: `X`
* not gate: `~`

Each gate but the last one takes two inputs. Inputs are from a `.` in the top left and bottom left corners of the 3 by 3 square centered on the gate. For not, the input is directly to its left. Output is to a `.` directly to the right.

Wires are represented by `-|\/.=`

* `-` contacts two wires, one to the right, and one to the left: `c-c`
* `|` contacts two wires, one above, and one below:

```
c
|
c

```
* `/` and `\` work as follows:

```
c        c
 \      /
  c    c

```
* `.` contacts every surrounding wire:

```
ccc
c.c
ccc

```
* `=` is special; it connects adjacent wires across it:

```
-=-

```

connects the two wires. In the following

```
\|/
-=-
/|\

```

each opposite wire is connected with each other, but not the others (this is where it differs from `.`).
* In order for current to flow, two wires must both be connected to the other one, so in `|-`, current does **not** flow.

Example of wiring:

```
      .-.
     =   \
 .--. .---=---
-.   =     .--
 .--. .-------

```

the input is split into two wires and then split into three. In this split, the bottom wire moves to the middle, and the downwards split of the top wire appears on the bottom. Next, the top of the three wires is moved to the middle.

Sample wiring with gates:

```
--.
   o..~..
--.      o.---
   a.---.
--.

```

Input format:

* each input wire will be labeled with a digit. At the end (right before newline), each output will be labeled with `:` (and the wire will always go **right** into it, ie `-:` or `.:` or `=:`)
* the input will always be valid; there will be no loops or wires joining together without a gate. Note that there can be wires with loose ends.
* `=` will be used only when necessary.

Output format:

* each input is referenced with the corresponding number.
* an expression is outputted. For example, if the wires compute input 1 and input 2, the output is `1a2`.
* whatever functions outputted must correspond to the logic gates at the beginning.
* to show not, put the `~` before the correct place.
* for multiple functions, use parentheses to show the order of execution. Parentheses can also be used when there is only a single function. For example,

```
1-.~.-.
       A.~.-:
      .
2-.  /
   x.
3-.

```

has one possible output of `~((2x3)A(~1))`
* multiple outputs must be separated by a newline (or equivalent)

Sample input:

```
1--.---.
    x.  \
2--.  x.-=---------.
     .    .~.       X.--.
3---. .      a.----.   /
       O.~.-.       \ /
      .              =
4-.  /              / .-:
   X.              .----:
5-.

```

One possible corresponding output:

```
(~1)a(~(3O(4X5))
((1x2)x3)X((~1)a(~(3O(4X5))))

```

# Answer
> 4 votes
# Python ~~2488~~ ~~1567~~ ~~806~~ ~~706~~ ~~697~~ ~~657~~ 653

Yay for gzip + exec!

```
import zlib,base64;exec zlib.decompress(base64.b64decode('eNp1U8FuqzAQvPMV7sm2gBSuuFupX9BLD5UoBxNMMAkEgQmJVPXb364Daiu9ntaznt2dWYzthvPo2HSbgsrU7E3so0FmAWtgnyeFshjSImC2Zs1Tws4js/fQPMPJ9KKTlFrPeVPIbDRuHnvOA3YByuS2UCNwrloYqOMRQ1ooDY0qwaoKRJxGSZRKP+QCwBn/0YRyzPYcYq77irUATVbGcIytGkN4E7mOyiLayx/MT888AthMx9DGDTLj/zIfPz44emUGqC/Zoio1UdFzohzFp0TNNA7xQhFxDWJiNGNG98L54yLVYUsv3+kZx9G8/uyEoQFk8NELrDeIIggf5Cb3b3/I3nnFNdZe0QOrCHl4+4ZsgVyH16gMb4XHq4IrwA0gkV7kAwyZH7Fs7f0S/O7IbnZX7jelzy+v13f8LsAFD0kVfrQyTklZyCUPL+F2Ef66WHug7i9f/bWyfnOIsrNTZQ/WCXxCcAnY/QmwMeggLwIyeCKD+FB3k6tsj/K6nR4G01fiZCcnTlIGBkw/d2bUzvgSG2kqMvhOkU+ZNirvGS1XgyWKy/xS2TDa3uE/kNuoJX0UC/kP8j/kmA=='))

```

---

### Limitations and assumptions

As it is, only up to 9 inputs are supported - multiple digits are not handled correctly. As the spec indicates that inputs are labelled with a *digit*, not a *number*, this is allowed.

---

### Input and output

Input is taken via standard in, and output is via standard out.

---

### Testing

Sample input and output:

```
1--.---.
    x.  \
2--.  x.-=---------.
     .    .~.       X.--.
3---. .      a.----.   /
       O.~.-.       \ /
      .              =
4-.  /              / .-:
   X.              .----:
5-.

```

```
(~(1))a(~((3)O((4)X(5))))
(((1)x(2))x(3))X((~(1))a(~((3)O((4)X(5)))))

```

Tested here: http://ideone.com/gP4CIq

---

### The algorithm

It's basically a rather naive DFS from the outputs. For each output, it starts from the character one to its left and traces the wire, branching (and adding to the expression) at every gate. When it reaches an input, it adds it to the expression and backtracks to the last point it branched, since we can be sure that branching is *not* possible without a gate. And of course any invalid cases are discarded. Nothing really special to it - and therefore it's likely longer than it could have been.

---

### Notes

Size could probably be reduced a fair bit with some restructuring, but I've spent enough time on this for today. The manually golfed version was the one compressed.

The gzip compression makes golfing interesting, because certain caching (e.g. `d=(-1,0,1)`) actually takes more space than letting the compression algorithm take care of it. However, I opted to golf the manual version as far as possible rather than optimising for compression.

---

### Manually golfed (~~909~~ ~~895~~ ~~840~~ 803):

```
import sys
def T(c,p):
 h=c[0];i=c[1]
 if h<0 or i<0 or h>=len(m)or i>=len(m[h]):return''
 v=m[h][i];r='';j=p[0];k=p[1];a=h;b=i;d=(-1,0,1)
 if v==' ':return''
 if v in'=-'and j==h:b-=k-i;r+=T([a,b],c)
 if v in'=|'and k==i:a-=j-h;r+-T([a,b],c)
 if v in'=/\\':
  e=j==h or k==i;s=j-h>0;t=j-h<0;u=k-i>0;w=k-i<0;f=(s and u)or(t and w);g=(s and w)or(t and u)
  if not(e or v=='/'and f or v=='\\'and g):a-=j-h;b-=k-i;r+=T([a,b],c)
 if v=='.':
  for x in d:
   for y in d:
    w=[a+x,b+y]
    if not(x==y==0)and w!=p:r+=T(w,c)
 if j==h and k-i>0:
  if v in'aoAOxX':r='('+T([a-1,b-1],c)+')'+v+'('+T([a+1,b-1],c)+')'
  if v=='~':r='~('+T([a,b-1],c)+')'
 if v.isdigit():r=v
 return r
m=[]
for l in sys.stdin:
 m.append(list(l))
e=enumerate
for i,a in e(m):
 for j,b in e(a):
  if b==':':
   print T([i,j-1],[i,j])

```

### Full ungolfed (2488):

```
import sys

def findOuts(c):
    for i, iVal in enumerate(c):
        for j, jVal in enumerate(iVal):
            if jVal == ':':
                yield [i, j]

def trace(pos, prev):
    if pos[0] < 0 or pos[1] < 0 or pos[0] >= len(circuit) or pos[1] >= len(circuit[pos[0]]):
        return ''
    val = circuit[pos[0]][pos[1]]
    if val == ' ':
        return ''
    next = pos[:]
    ret = ''
    if val in '=-':
        if prev[0] == pos[0]:
            next[1] -= prev[1] - pos[1]
            ret += trace(next, pos)
    if val in '=|':
        if prev[1] == pos[1]:
            next[0] -= prev[0] - pos[0]
            ret += trace(next, pos)
    if val in '=/\\':
        # top-bottom, left-right
        tblr = prev[0] == pos[0] or prev[1] == pos[1]
        # top-left, bottom-right
        tlbr = (prev[0] - pos[0] == 1 and prev[1] - pos[1] == 1) or (prev[0] - pos[0] == -1 and prev[1] - pos[1] == -1)
        # top-right, bottom-left
        trbl = (prev[0] - pos[0] == 1 and prev[1] - pos[1] == -1) or (prev[0] - pos[0] == -1 and prev[1] - pos[1] == 1)
        if not ((val == '/' and (tlbr or tblr)) or (val == '\\' and (trbl or tblr)) or (val == '=' and tblr)):
            next[0] -= prev[0] - pos[0]
            next[1] -= prev[1] - pos[1]
            ret += trace(next, pos)

    if val == '.':
        for x in (-1,0,1):
            for y in (-1,0,1):
                if x == y == 0:
                    continue

                w = [next[0] + x, next[1] + y]
                if w == prev:
                    continue

                # only one of them should return anything
                ret += trace(w, pos)

    # assumption that a logic gate always has a . on its connections, as according to spec
    if val in 'aoAOxX':
        # only from the right/output
        if not (prev[0] == pos[0] and prev[1] == pos[1] + 1):
            return ret
        ret = '(' + trace([next[0] - 1, next[1] - 1], pos) + ')' + val + '(' + trace([next[0] + 1, next[1] - 1], pos) + ')'

    if val == '~':
        # only from the right/output
        if not (prev[0] == pos[0] and prev[1] == pos[1] + 1):
            return ret
        ret = '~(' + trace([next[0], next[1] - 1], pos) + ')'

    if val in '123456789':
        ret = val

    return ret

circuit = []
for line in sys.stdin.readlines():
    # padding added to prevent index out of bounds later
    circuit.append(list(line))

for out in findOuts(circuit):
    next = out[:]
    next[1] -= 1
    print trace(next, out)

```

# Answer
> 6 votes
# Java: ~~1523~~ 1512 chars

```
import java.util.*;class W{int v=99;Map<Integer,String>t;boolean k;public static void main(String[]y){new W().d();}W(){try{java.io.InputStream i=new java.io.File("r").toURL().openStream();t=new HashMap<>();int a=0,x=0,y=0;while((a=i.read())>-1){if(a==10){y++;x=0;continue;}q(x,y,(a>47&a<58?"!":"")+(char)a);x++;}}catch(Exception e){}}void d(){while(!k){k=!k;for(Map.Entry<Integer,String>g:t.entrySet())e(g.getKey(),g.getValue());}for(String b:t.values())if(b.startsWith("$"))System.out.println(b.substring(1));}void e(int a,String s){if(s==null||!s.startsWith("!"))return;int x=a/v,y=a%v;s=s.substring(1);b(s,x,y,x-1,y+1);b(s,x,y,x,y+1);b(s,x,y,x+1,y+1);b(s,x,y,x-1,y);b(s,x,y,x+1,y);b(s,x,y,x-1,y-1);b(s,x,y,x,y-1);b(s,x,y,x+1,y-1);}void b(String p,int m,int n,int x,int y){String s=t.get(x*v+y);if(s==null)return;boolean g=y==n+1;boolean h=y==n-1;boolean i=x==m+1;boolean j=x==m-1;if(z(s,"-=")&n==y){if(i)b(p,x,y,x+1,y);if(j)b(p,x,y,x-1,y);}if(z(s,"|=")&m==x){if(g)b(p,x,y,x,y+1);if(h)b(p,x,y,x,y-1);}if(z(s,"/=")){if(j&g)b(p,x,y,x-1,y+1);if(i&h)b(p,x,y,x+1,y-1);}if(z(s,"\\=")){if(i&g)b(p,x,y,x+1,y+1);if(j&h)b(p,x,y,x-1,y-1);}if(z(s,".")){q(x,y,"!"+p);u();}if(z(s,"~")){q(x,y,"!~("+p+")");u();}if((s.charAt(0)=='%'&n==y-1)|(s.charAt(0)=='&'&n==y+1)){q(x,y,"!("+p+")"+s.charAt(1)+"("+s.substring(2)+")");u();}if(z(s,"OoAaXx")){q(x,y,(n==y+1?"%":"&")+s+p);u();}if(z(s,":")){q(x,y,"$"+p);u();}}void q(int x,int y,String z){t.put(x*v+y,z);}void u(){k=false;}boolean z(String s,String c){return c.indexOf(s)>-1;}}

```

It gives this output for the sample input:

```
(~(((5)X(4))O(3)))a(~(1))
((~(((5)X(4))O(3)))a(~(1)))X(((2)x(1))x(3))

```

In order to squeeze its size:

* It does not do any error checking, error handling or input validation, assuming that the input is always valid.
* Is limited to 99 lines of input.
* Its input file must be called just `r`, without any file extension in the name.
* It does not makes any effort to detect if the parenthesis are or aren't necessary. It assumes that they always are necessary, and since this assumption is false, there is a lot more parenthesis than needed, but since this does not makes it fail the spec anyway, it is no problem.
* The order of the parameters to each binary operator is in general unpredictable, as it depends on the velocity that the values are propagated and from cell scanning order. But since all the binary operators are commutative, this should be no problem.

I am sure that it should be possible to reduce it more, but just a bit.

The interpreter is implemented in the form of some sort of cellular automata. It scans the entire field setting values, repeating it as many times as needed until no changes are detected.

Here is an ungolfed version:

```
import java.util.*;

class Wiring {

    int maxLines = 99;
    Map<Integer, String> circuitState;
    boolean finished;

    public static void main(String[] args) {
        new Wiring().interpret();
    }

    Wiring() {

        try {
            // Always read the input from the "r" file, and do not check if it even
            // exists. BTW, the toURL() method is deprecated, but we don't care about
            // this in code-golfing.
            java.io.InputStream stream = new java.io.File("r").toURL().openStream();

            circuitState = new HashMap<>();
            int byteRead = 0, cellX = 0, cellY = 0;

            while ((byteRead = stream.read()) > -1) {

                // Check for line break;
                if (byteRead == 10) {
                    cellY++;
                    cellX = 0;
                    continue;
                }

                // Populate the circuit cell. Precede numbers with an exclamation mark.
                setCircuitCell(cellX, cellY, (byteRead >= '0' & byteRead <= '9' ? "!" : "") + (char) byteRead);
                cellX++;
        } catch (Exception e) {
        }
    }

    void interpret() {
        while (!finished) {
            finished = !finished; // i.e. finished = false;
            for (Map.Entry<Integer, String> entry : circuitState.entrySet()) {
                analyzeCell(entry.getKey(), entry.getValue());
            }
        }

        // Now print the output. To do that scan for cells marked with "$".
        for (String cell : circuitState.values()) {
            if (cell.startsWith("$")) System.out.println(cell.substring(1));
        }
    }

    void analyzeCell(int cellIndex, String cellValue) {
        // Only the cells with a value marked with "!" are worth to analyze.
        if (cellValue == null || !cellValue.startsWith("!")) return;

        // Convert the cellIndex to a bidimensional coordinate.
        int x = cellIndex / maxLines, y = cellIndex % maxLines;

        // Remove the "!".
        cellValue = cellValue.substring(1);

        // Propagate the cell value to neighbouring cells.
        propagateCellData(cellValue, x, y, x - 1, y + 1);
        propagateCellData(cellValue, x, y, x, y + 1);
        propagateCellData(cellValue, x, y, x + 1, y + 1);
        propagateCellData(cellValue, x, y, x - 1, y);
        propagateCellData(cellValue, x, y, x + 1, y);
        propagateCellData(cellValue, x, y, x - 1, y - 1);
        propagateCellData(cellValue, x, y, x, y - 1);
        propagateCellData(cellValue, x, y, x + 1, y - 1);
    }

    void propagateCellData(String cellValue, int sourceX, int sourceY, int targetX, int targetY) {
        String targetContent = circuitState.get(targetX * maxLines + targetY);

        // If the target cell does not exist, just ignore.
        if (targetContent == null) return;

        boolean targetBelowSource = targetY == sourceY + 1;
        boolean targetAboveSource = targetY == sourceY - 1;
        boolean targetRightToSource = targetX == sourceX + 1;
        boolean targetLeftToSource = targetX == sourceX - 1;

        // Propagate horizontally through wires.
        if (isStringContained(targetContent, "-=") & sourceY == targetY) {
            if (targetRightToSource) propagateCellData(cellValue, targetX, targetY, targetX + 1, targetY);
            if (targetLeftToSource) propagateCellData(cellValue, targetX, targetY, targetX - 1, targetY);
        }

        // Propagate vertically.
        if (isStringContained(targetContent, "|=") & sourceX == targetX) {
            if (targetBelowSource) propagateCellData(cellValue, targetX, targetY, targetX, targetY + 1);
            if (targetAboveSource) propagateCellData(cellValue, targetX, targetY, targetX, targetY - 1);
        }

        // Propagate in the diagonal x=-y.
        if (isStringContained(targetContent, "/=")) {
            if (targetLeftToSource & targetBelowSource) {
                propagateCellData(cellValue, targetX, targetY, targetX - 1, targetY + 1);
            }
            if (targetRightToSource & targetAboveSource) {
                propagateCellData(cellValue, targetX, targetY, targetX + 1, targetY - 1);
            }
        }

        // Propagate in the diagonal x=y.
        if (isStringContained(targetContent, "\\=")) {
            if (targetRightToSource & targetBelowSource) {
                propagateCellData(cellValue, targetX, targetY, targetX + 1, targetY + 1);
            }
            if (targetLeftToSource & targetAboveSource) {
                propagateCellData(cellValue, targetX, targetY, targetX - 1, targetY - 1);
            }
        }

        // If we got a dot, store the value there.
        // Do not forget to mark it with "!", so we can rescan it later.
        if (isStringContained(targetContent, ".")) {
            setCircuitCell(targetX, targetY, "!" + cellValue);
            markThatStateChanged();
        }

        // If we got a "~", store the inverted value there.
        // Do not forget to mark it with "!", so we can rescan it later.
        if (isStringContained(targetContent, "~")) {
            setCircuitCell(targetX, targetY, "!~(" + cellValue + ")");
            markThatStateChanged();
        }

        // If we found a binary logical port with one of the values set and
        // we can set the another value, do it. Use "%" and "&" to know which
        // one was already defined.
        // BTW, do not forget to mark it with "!", so we can rescan it later.
        if ((targetContent.charAt(0) == '%' & sourceY == targetY - 1)
                | (targetContent.charAt(0) == '&' & sourceY == targetY + 1))
        {
            setCircuitCell(targetX, targetY,
                    "!(" + cellValue + ")"
                    + targetContent.charAt(1)
                    + "(" + targetContent.substring(2) + ")");
            markThatStateChanged();
        }

        // Found a binary logical port without any value setted, so set it.
        // Use "%" and "&" to mark which one was setted.
        if (isStringContained(targetContent, "OoAaXx")) {
            setCircuitCell(targetX, targetY, (sourceY == targetY + 1 ? "%" : "&") + targetContent + cellValue);
            markThatStateChanged();
        }

        // If we found an output, store the value there.
        // Mark it with "$", so we will print it in the future.
        if (isStringContained(targetContent, ":")) {
            setCircuitCell(targetX, targetY, "$" + cellValue);
            markThatStateChanged();
        }
    }

    void setCircuitCell(int cellX, int cellY, String cellContents) {
        circuitState.put(cellX * maxLines + cellY, cellContents);
    }

    void markThatStateChanged() {
        finished = false;
    }

    boolean isStringContained(String searchingString, String searchTarget) {
        return searchTarget.indexOf(searchingString) > -1;
    }
}

```

---
Tags: code-golf, parsing
---


title: Mod 7 in Manufactoria

text:
# Question
Title: Mod 7 in Manufactoria
A simple Manufactoria challenge. Compute the input modulo 7. The input will be in big-endian binary (blue=1, red=0). The output should be in the same format.

Test cases provided. The smallest part count wins.

http://pleasingfungus.com/Manufactoria/?ctm=Mod7;Input:\_binary\_number\_big\_endian.\_Output:\_that\_binary\_number\_mod\_7;bbb:|brrr:b|brrrr:br|bb:bb|bbrrb:brr|brrrrb:brb|bbrb:bbr;13;3;1;

(if the input mod 7 is 0, output nothing.)

# Answer
> 5 votes
The algorithm is quite straightforward: Compute the modulus using a state machine (the largest part with eight branches - one of the states is duplicated for logistical purposes), then encode and collect the results. Since almost every result contains a one digit, an extra compression step is employed to reduce the amount of parts.

Designed in yEd, then transcribed to Manufactoria.

Uses way too many conveyer belts, in my opinion.

# Answer
> 5 votes
# ~~58~~ 43 parts

http://pleasingfungus.com/Manufactoria/?lvl=33&code=c16:9f0;q15:9f3;q14:9f3;q13:9f3;c12:9f3;c16:10f1;r15:10f3;r14:10f3;b13:10f3;q12:10f4;p11:10f4;c16:11f1;i15:11f7;q14:11f7;q13:11f7;q12:11f7;c11:11f2;r15:12f3;b14:12f3;c12:12f3;c15:13f0;c14:13f0;c13:13f0;r13:12f3;y10:3f3;c10:4f2;g10:5f1;q10:6f4;y11:3f0;q11:4f6;r11:5f3;p11:6f4;b11:7f1;i12:4f7;c12:5f3;q12:6f0;g12:2f3;c12:3f3;p13:4f6;y13:3f0;c13:5f0;c12:7f3;b12:8f3;&ctm=Mod7;Input:\_binary\_number\_big\_endian.\_Output:\_that\_binary\_number\_mod\_7;bbb:|brrr:b|brrrr:br|bb:bb|bbrrb:brr|brrrrb:brb|bbrb:bbr;13;3;1;

Keith Randall's idea of first converting the input to unary was pretty good, so I stole it. ;-) Conveniently, I'd just spent some time optimizing small binary-to-unary converters in Manufactoria, so just picked one of my almost-working solutions\* from that challenge and combined it with a quickly optimized mod-7 counter.

This design is now at the point where just getting the robots from the top to the bottom is starting to require otherwise useless extra conveyors. Any significant further parts reductions will probably come from redesigning the layout to be taller and narrower.

(\* That challenge required a) the design to fit onto a 7×7 board, and b) the unary output to be in red markers. If you look at the binary-to-unary converter part of the machine above, you'll note that, with one or two extra parts, it can easily satisfy either requirement, but alas, not both.)

---

Here's the previous 58-part version:

http://pleasingfungus.com/Manufactoria/?lvl=32&code=g12:2f3;q13:13f5;c14:13f0;c15:12f3;c9:6f2;c9:7f1;c9:8f1;c9:9f1;c10:4f3;c10:5f3;i10:6f5;c10:7f2;c10:9f0;b11:3f2;p11:4f1;c11:5f1;p11:6f2;p11:7f2;c11:8f3;p11:9f3;b11:10f2;c12:3f2;c12:4f2;c12:5f0;r12:6f3;c12:7f3;i12:8f1;i12:9f5;y12:10f3;c13:3f2;c13:4f3;i13:5f1;c13:6f3;c13:7f2;i13:8f0;c13:9f1;c14:3f3;c14:4f2;p14:5f5;c14:6f1;p14:7f6;p14:8f7;r14:9f3;c15:4f3;q15:5f0;c15:6f3;c15:7f3;i15:8f6;c15:9f3;q15:10f7;c15:11f3;r12:12f2;p13:12f7;b14:12f0;b14:11f3;b12:11f3;y14:10f3;y15:13f0;&ctm=Mod7;Input:\_binary\_number\_big\_endian.\_Output:\_that\_binary\_number\_mod\_7;bbb:|brrr:b|brrrr:br|bb:bb|bbrrb:brr|brrrrb:brb|bbrb:bbr;13;3;1;

Like Jan Dvorak's solution, this is also based on a 7-state FSM. I've labeled the gates corresponding to each state in the screenshot to make it easier to read. The state machine itself, however, is really the easy part; the tricky part is generating the final output with a minimal number of gates.

One trick I found useful was the final copy loop that barrel-shifts everything written before the yellow marker to the end (while also stripping off the green marker): this allowed me to make use of the repetition in the high-order output bits by generating the outputs as:

```
0:  Y   ->
1: BY   ->   B
2:  YBR ->  BR
3:  YBB ->  BB
4: RYBR -> BRR
5: BYBR -> BRB
6: RYBB -> BBR

```

This lets me mostly combine the output paths for outputs 2, 4 and 5 (which all begin with `BR`) and 3 and 6 (which begin with `BB`).

# Answer
> 2 votes
## 60 parts

My solution is quite a bit different. It converts binary to unary first, then does the mod 7. I can't quite beat Ilmari.

# Answer
> 0 votes
I actually had no idea what I'm doing but it works and I might be the winner (if only the test-cases would be proof enough). :D

EDIT: Optimized it 2 times, a bit smaller now.(Removed rubbish)

---
Tags: code-golf, manufactoria
---


title: Mechanical Coding

text:
# Question
Title: Mechanical Coding
The goal is to calculate the output speed of a series of cogs. The winner will be chosen by popular vote.

The arrangement of cogs is defined in an ASCII-art string:

> `O` large cog
> `o` medium cog
> `*` small cog
> `-` axle (one or more in a row)
> `=` chain (one or more in a row)

An example input is:

```
o*-O*==oO

```

> `o` medium cog, meshed with `*` small cog, attached by `-` axle to `O` large cog, meshed with `*` small cog, connected by `==` chain to medium cog, meshed with `O` large cog.

The code takes five inputs by command line argument, standard in, or function parameter:

> Arrangement
> Number of teeth on large cogs
> Number of teeth on medium cogs
> Number of teeth on small cogs
> Left-side speed in teeth per second (+ve is clockwise, -ve is anti-clockwise)

And outputs:

> Right-side speed in teeth per second

Interactions between cogs and other components occur as follows:

> SL = Speed of left cog
> SR = Speed of right cog
> TL = Teeth of left cog
> TR = Teeth of right cog
>
> ### Two meshed cogs
>
> `O*`
> SR = -SL
>
> ### Two cogs connected by a chain of any length
>
> `O===*`
> SR = SL
>
> ### Two cogs connected by an axle of any length
>
> `O---*`
> SR = SL * TR / TL

Any invalid arrangement can throw an error or return 0.

## Test Cases

```
arrangement     O   o   *  speed  =>  speed

*-Oo-O         50  30  10    3.0  =>  -25.0
o*-O*==oO      50  30  10   -3.0  =>   15.0
O---*oO=O*-oo  15  12   8   10.0  =>    8.0
=o*            50  30  10   10.0  =>  error
o*-            50  30  10   10.0  =>  error
o-=*           50  30  10   10.0  =>  error
o *            50  30  10   10.0  =>  error

```

# Answer
> 6 votes
# Javascript – animated version

Playing on with canvas again. Adding a sample going far out of the scope of the task. But, anyhow, here it is. It is an animated / paint version.

### *Issues*

Can be a resource hog. In some quick tests it runs best in Chrome, worse in Opera and worst in Firefox. There is also an issue with movement as on relatively high speeds as the turn on each frame gets too big.

If one use small value for *Teeth Width*, it performs OK in various cases. *Decor* also has an impact.

By choice the use of *Animation Frame* or *interval* can be selected, and while using *interval* frames per second (FPS) can be tweaked. FPS can easily be lower then set if painting one frame takes longer.

If it only hogs, one can also use it to simply paint still images. Press *Stop* button and enter string to be parsed. With full decor it can be for a nice picture ;)

Try it out in this Fiddle.

Javascript code:

*It could definitively have been tidied up some more and refactored.*

`requestAnimationFrame` *polyfill* removed in this post due to limit of body length on SO.

```
var PI  = Math.PI,
    P2  = PI*2,
    cos = Math.cos,
    sin = Math.sin;

function isNumber(n) {
    return !isNaN(parseFloat(n)) && isFinite(n);
}

function isNumbers(a) {
    var i;
    for (i = 0; i < a.length; ++i)
        if (!isNumber(a[i]))
            return 0;
    return 1;
}

function CogWheels() {
    this.can    = document.getElementById('can');
    this.ctx    = this.can.getContext("2d");
    this.cm = {
        main:{can: document.createElement('CANVAS'),ok:0}
        //gear:{can: document.createElement('CANVAS'),ok:0}
    };
    this.cm.main.ctx = this.cm.main.can.getContext("2d");

    this.ofs    = {x:10, y:50};
    this.grect  = null;

    this.parts  = [];
    this.pix    = {wheel:[],axle:[],chain:[]};

    this.sz     = {rb:100, rm:75, rs:50};
    this.dir    = 1;
    this.last   = null;
    this.tw     = 4;
    this.tl     = this.tw + 1;
    this.navcr  = 7.5;

    this.tsp    = null; // Timestamp previus frame
    this.raf    = 0;    // Use requestAnimationFrame
    this.mode   = 0;    // 1=Auto start
    this.decor  = 3;    // Decoration level
    this.shade  = 1;    // Use shading
    this.pin    = 1;    // Paint "pin"
    this.clr = {
        wheel: '#321',
        axle : '#852',
        chain: '#842',
        axis : '#a50',
        teeth: '#1a1108',
        pin  : '#f00',
        dec1 : '#321'
    };
}

var CW = CogWheels.prototype;

CW.getShadow = function() {
    return {
        x:this.ctx.shadowOffsetX,
        y:this.ctx.shadowOffsetY,
        b:this.ctx.shadowBlur,
        c:this.ctx.shadowColor.match(/\((.*)\)/)[1]
    };
};

CW.setShadow = function(p) {
    this.ctx.shadowOffsetX  = p.x || 0;
    this.ctx.shadowOffsetY  = p.y || 0;
    this.ctx.shadowBlur     = p.b || 5;
    this.ctx.shadowColor    = p.c ? "rgba("+p.c+")" : "rgba(0,0,0,.8)";
};

CW.noShadow = function() {
    this.setShadow({x:0, y:0, b:0, c:"0,0,0,0"});
};

/*
 * Drawings for static buffer.
 *
 * * */
CW.drawBulb = function(x, y, r) {
    var gradient = this.ctx.createRadialGradient(x, y, 0, x, y, r);
    gradient.addColorStop(1.00, 'rgba(0, 0, 0, 0)');
    gradient.addColorStop(0.95, 'rgba(40, 40, 40, 1)');
    gradient.addColorStop(0.85, 'rgba(85, 85, 85, 1)');
    gradient.addColorStop(0.70, 'rgba(170, 170, 170, 1)');
    gradient.addColorStop(0.40, 'rgba(250, 250, 250, 1)');
    gradient.addColorStop(0.00, 'rgba(255, 255, 255, 1)');
    this.ctx.fillStyle = gradient;
    this.ctx.globalCompositeOperation = 'source-over';
    this.ctx.fillRect(x - r, y - r, x + r, y + r);
    this.ctx.fillStyle = "#000";
};

CW.drawWheel = function(p) {
    this.ctx.save();
    this.ctx.globalCompositeOperation = 'source-over';
    this.ctx.lineWidth      = this.tw;
    this.ctx.strokeStyle    = this.clr.wheel;
    this.ctx.moveTo(p.a[0], p.a[1]);
    this.ctx.beginPath();
    this.ctx.arc(p.a[0], p.a[1], p.r, 0, P2, p.d);
    this.ctx.stroke();
    if (this.decor > 0 && p.r > 10) {
        this.ctx.beginPath();
        this.ctx.strokeStyle = '#444';
        this.ctx.lineWidth = 1;//0.8;
        this.ctx.arc(p.a[0], p.a[1], p.r / 1.15, 0, P2, p.d === 1);
        this.ctx.stroke();
    }

    // Axis
    this.ctx.beginPath();
    this.ctx.globalCompositeOperation = 'xor';
    this.ctx.lineWidth = 1.5;
    this.ctx.strokeStyle = this.clr.axis;
    this.ctx.arc(p.a[0], p.a[1], this.navcr, 0, P2);
    this.ctx.stroke();
    this.ctx.restore();
    //this.ctx.globalCompositeOperation = 'source-over';
};

CW.drawLinep = function(a) {
    this.ctx.beginPath();
    this.ctx.moveTo(a[0][0], a[0][1]);
    this.ctx.lineTo(a[0][2], a[0][3]);
    this.ctx.moveTo(a[1][0], a[1][1]);
    this.ctx.lineTo(a[1][2], a[1][3]);
    this.ctx.stroke();
};

CW.drawAxle = function(p) {
    this.ctx.save();
    this.ctx.shadowOffsetX  = -this.tw/2;
    this.ctx.shadowOffsetY  = this.tw/2;
    this.ctx.globalCompositeOperation = 'source-over';
    this.ctx.lineWidth = 2;
    this.ctx.strokeStyle = this.clr.axle;

    this.drawLinep(p.a);

    this.noShadow();
    /* Nav left wheel. */
    this.ctx.beginPath();
    this.ctx.lineWidth = 3;
    this.ctx.globalCompositeOperation = 'xor';
    this.ctx.arc(p.a[0][0], p.pp[1], this.navcr, 0, P2);
    this.ctx.stroke();

    /* Nav right wheel. */
    this.ctx.beginPath();
    this.ctx.arc(p.a[0][2], p.pp[1], this.navcr, 0, P2);
    this.ctx.stroke();

    this.ctx.restore();
};

CW.drawChain = function(p) {
    this.ctx.save();
    this.ctx.lineWidth = 2;
    this.ctx.strokeStyle = this.clr.chain;
    this.ctx.globalCompositeOperation = 'destination-over';
    this.ctx.shadowOffsetX  = -this.tw/2;
    this.ctx.shadowOffsetY  = this.tw/2;

    this.drawLinep(p.a);

    this.ctx.restore();
};

CW.circleTangents = function(x1, y1, r1, x2, y2, r2) {
    var d = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)),
        vx = (x2 - x1) / d,
        vy = (y2 - y1) / d,
        s1, s2, c, h,
        nx, ny, a, re = [], i = 0;
    for (s1 = 1; s1 >= -1; s1 -= 2) {
        c = (r1 - s1 * r2) / d;
        if (c*c > 1.0)
            continue;
        h = Math.sqrt(Math.max(0.0, 1.0 - c * c));
        for (s2 = 1; s2 >= -1; s2 -= 2) {
            nx = vx * c - s2 * h * vy;
            ny = vy * c + s2 * h * vx;
            a = [];
            a[0] = x1 + r1 * nx;
            a[1] = y1 + r1 * ny;
            a[2] = x2 + s1 * r2 * nx;
            a[3] = y2 + s1 * r2 * ny;
            re[i++] = a;
        }
    }
    return re;
};

/*
 * Paint gear base to static buffer.
 *
 * */
CW.drawStatic = function() {
    var sh;

    if (this.cm.main.ok) {
        sh = this.getShadow();
        this.noShadow();
        this.ctx.drawImage(
            this.cm.main.can,
            this.cm.main.x,
            this.cm.main.y
        );
        this.setShadow(sh);
        return;
    }
};

CW.genStatic = function() {
    var i, e,
        p   = this.parts,
        ix  = this.pix;

    this.ctx.save();
    if (this.shwheel) {
        for (i = 0; i < ix.wheel.length; ++i) {
            e = p[ix.wheel[i]];
            this.drawBulb(e.a[0], e.a[1], e.r);
        }
    }
    for (i = 0; i < ix.wheel.length; ++i) {
        this.drawWheel(p[ix.wheel[i]]);
        //setTimeout(this.drawWheel.bind(this, p[ix.wheel[i]]), (tt+=500));
    }
    for (i = 0; i < ix.axle.length; ++i) {
        this.drawAxle(p[ix.axle[i]]);
        //setTimeout(this.drawAxle.bind(this, p[ix.axle[i]]), (tt+=500));
    }
    for (i = 0; i < ix.chain.length; ++i) {
        this.drawChain(p[ix.chain[i]]);
        //setTimeout(this.drawChain.bind(this, p[ix.chain[i]]), (tt+=500));
    }
    for (i = 0; i
 10)
            this.ctx.fillText(i, p[i].pp[0], p[i].pp[1]);
        else if (p[i].w === 'wheel')
            this.ctx.fillText('x', p[i].pp[0], p[i].pp[1]);
    }
    this.cm.main.can.width  = this.grect.w - this.ofs.x + 20;
    this.cm.main.can.height = this.br * 2 + 40;
    // Could have painted directly on memory canvas, but due to coordinates
    // and post-implementation of memory canvas, it is here for now.
    this.cm.main.ctx.drawImage(
        this.can,                       // image
        0,                              // dx
        0,                              // dy
        this.grect.w - this.ofs.x,      // dw
        this.br * 2 + 60,               // dh WHY 60 HERE ????
        -this.ofs.x + 20,               // sx
        -this.ofs.y + 20,               // sy
        this.grect.w - this.ofs.x ,     // sw
        this.br * 2 + 60                // sh WHY 60 HERE ????
    );
    this.cm.main.x = this.ofs.x - 20;
    this.cm.main.y = this.ofs.y - 20;
    this.cm.main.ok = 1;
    this.ctx.restore();
};

/*
 * Drawings for moving parts.
 *
 * * */
CW.spikes = function(x1, y1, spikes, r0, r1, skew_0, skew_1, con) {
    var t = PI / 2 * 3,
        x = x1,
        y = y1,
        step = PI / spikes,
        i, r2 = con ? r1 - 10 : r1;

    this.ctx.beginPath();
    this.ctx.moveTo(x1, y1 - r0);
    for (i = 0; i < spikes; ++i) {
        x = x1 + cos(t)*r0;
        y = y1 + sin(t)*r0;
        this.ctx.lineTo(x, y);
        if (skew_0) {
            t += step / 2;
            x = x1 + cos(t)*r0;
            y = y1 + sin(t)*r0;
            this.ctx.lineTo(x, y);
            t += (step - step/2);
        } else {
            t += step;
        }

        if (skew_1) {
            x = x1 + cos(t - step/18) * r2;
            y = y1 + sin(t - step/18) * r2;
            this.ctx.lineTo(x, y);
            if (con) {
                x = x1 + cos(t - step/8) * r1;
                y = y1 + sin(t - step/8) * r1;
                this.ctx.lineTo(x, y);
                x = x1 + cos(t + step/8) * r1;
                y = y1 + sin(t + step/8) * r1;
                this.ctx.lineTo(x, y);
            }
            x = x1 + cos(t + step/18) * r2;
            y = y1 + sin(t + step/18) * r2;
            this.ctx.lineTo(x, y);
        } else {
            x = x1 + cos(t) * r1;
            y = y1 + sin(t) * r1;
            this.ctx.lineTo(x, y);
        }

        if (skew_0) {
            t += step / 2;
            x = x1 + cos(t)*r0;
            y = y1 + sin(t)*r0;
            this.ctx.lineTo(x, y);
            t += step - step/2;
        } else {
            t += step;
        }
    }
    this.ctx.lineTo(x1, y1 - r0);
    this.ctx.stroke();
    this.ctx.closePath();
};

CW.drawTeeth = function(p) {
    var i, th = p.h, x, y;
    for (i = 0; i < p.t; ++i) {
        x = p.pp[0] + p.r * cos(th);
        y = p.pp[1] + p.r * sin(th);
        this.ctx.moveTo(x, y);
        this.ctx.lineTo(x + cos(th) * this.tl, y + sin(th) * this.tl);
        th += p.thi;
    }
    return th;
};

CW.drawPin = function(p) {
    var x = p.pp[0] + p.r * cos(p.h),
        y = p.pp[1] + p.r * sin(p.h);
    this.ctx.moveTo(
        p.pp[0] + (this.navcr) * cos(p.h),
        p.pp[1] + (this.navcr) * sin(p.h)
    );
    this.ctx.lineTo(x + cos(p.h) * this.tl, y + sin(p.h) * this.tl);
};

CW.drawDecor1 = function(p) {
    var i, x, y,
        th = p.h,
        dd = p.r / 1.15 * 0.63,
        rr = (p.r / this.spk) * 1.125;

    this.ctx.strokeStyle = this.clr.dec1;
    this.ctx.lineWidth = 2;
    this.ctx.globalCompositeOperation = 'source-over';

    for (i = 0; i < this.spk; ++i) {
        x = p.pp[0] + dd * cos(th);
        y = p.pp[1] + dd * sin(th);
        this.ctx.moveTo(x, y);
        this.ctx.beginPath();
        this.ctx.arc(x, y, rr, 0, P2);
        this.ctx.stroke();
        th += PI/this.spk*2;
    }
    //return th;
};

CW.drawDecor2 = function(p) {
    var theta = p.h;
    this.ctx.save();
    this.ctx.translate(p.pp[0], p.pp[1]);
    this.ctx.rotate(theta - (PI / 2 * 3));
    if (this.shade)
        this.setShadow({c:"12,17,23,1",b:17, x:-2, y:2});
    this.ctx.lineWidth = 2;
    if (this.star)
        this.spikes(0, 0, this.spk, p.r / 6 /*this.navcr*/, p.r / 1.19);
    else if (p.r > 50)
        this.spikes(0, 0, this.spk, p.r / 6 /*this.navcr*/, p.r / 1.15, 1, 1, 1);
    else
        this.spikes(0, 0, this.spk, p.r / 6 /*this.navcr*/, p.r / 1.19, 1, 1);
    this.ctx.restore();
};

CW.drawAnim = function(tt) {
    var i, j,
        p = this.parts,
        ix = this.pix,
        sh = this.getShadow();

    this.ctx.save();

    if (this.decor > 1) {
        for (i = 0; i < ix.wheel.length; ++i) {
            if (p[ix.wheel[i]].r < this.navcr * 2)
                continue;
            if ((this.decor === 2 || this.decor > 3))
                this.drawDecor1(p[ix.wheel[i]]);
            if ((this.decor > 2))
                this.drawDecor2(p[ix.wheel[i]]);
        }
    }

    this.ctx.lineWidth = this.tw;

    this.noShadow();
    if (this.pin) {
        this.ctx.beginPath();
        this.ctx.strokeStyle = this.clr.pin;
        this.ctx.globalCompositeOperation = 'darker';
        for (i = 0; i < ix.wheel.length; ++i)
            this.drawPin(p[ix.wheel[i]]);
        this.ctx.stroke();
    }

    this.ctx.globalCompositeOperation = 'destination-over';
    this.ctx.strokeStyle = this.clr.teeth;
    this.ctx.beginPath();
    for (i = 0; i < ix.wheel.length; ++i) {
        j = ix.wheel[i];
        this.drawTeeth(p[j]);
        p[j].h += p[j].s * tt * p[j].d;
    }
    this.ctx.stroke();
    this.setShadow(sh);

    this.ctx.restore();
};

/*
 * Build functions.
 *
 * * */
CW.add = function(a) {
    var e = {
            w: a.type,
            r: a.rad,
            s: a.speed,
            d: this.dir,
            h: a.theta,
        };
    if (a.type === 'wheel') {
        if (this.last === 'wheel')
            this.dir = -this.dir;
        e.t     = a.teeth;
        e.d     = this.dir;
        // Theta increment
        e.thi   = PI / a.teeth * 2;
    } else if (a.type === 'axle' || a.type === 'chain') {
        e.t     = 30;
    } else {
        // Throw error
        return null;
    }
    e.hs = e.h; // Starting angle
    this.last = a.type;
    this.parts.push(e);
    this.grect.w += e.r * 2 + this.tl * 2;
    return this;
};

/*
 * Various calculations that is the same for each frame.
 *
 * */
CW.postBuild = function() {
    var i,
        x1 = this.ofs.x, x2,
        y1 = this.ofs.y + this.br, y2,
        p  = this.parts,
        c  = this.navcr,
        a, d, txl = this.navcr > 10 ? 5 : 15,
        tf = this.tw < 2 ? 2 : 3;

    this.ctx.textBaseline = "middle";
    this.ctx.fillText("tps:", 2, this.grect.h + txl);
    txl += 20;
    this.ctx.fillText("Hz:", 2, this.grect.h + txl);
    txl -= 10;
    this.ctx.textAlign = "center";

    for (i = 0; i < p.length; ++i) {
        if (p[i].w === 'wheel') {
            x1 += p[i].r;
            p[i].a = [x1, y1];
            p[i].tps = (1 / ((P2 / p[i].t) / p[i].s) * p[i].d).toFixed(1);
            if (this.navcr <= 10)
                this.ctx.fillText(i, x1, this.grect.h + 5);
            this.ctx.fillText(p[i].tps, x1, this.grect.h + txl);
            this.ctx.fillText((Math.abs(p[i].tps)/p[i].t).toFixed(tf) ,
                              x1, this.grect.h + txl + 20);
            this.pix.wheel.push(i);
        } else if (p[i].w === 'axle') { // AXLE
            x1 -= p[i-1].r + c;
            x2 = x1 + p[i-1].r + c + p[i].r*2 + c + p[i + 1].r;
            a = [];
            // Left - right nav, top
            a[0] = [x1, y1 - c, x2, y1 - c];
            // Left - right nav, bottom
            a[1] = [x1, y1 + c, x2, y1 + c];
            p[i].a = a;
            // Real center + radius
            d = x2 - x1;
            p[i].cc = [(x1+x2)/2, y1, d / 2];
            p[i].t  = d * 2 / this.tw;
            x1 += p[i - 1].r + c + p[i].r;
            this.pix.axle.push(i);
        } else if (p[i].w === 'chain') {  // CHAIN
            x1 -= p[i-1].r + c;
            x2 = x1 + p[i-1].r + c + p[i].r*2 + c + p[i + 1].r;
            y2 = y1 - p[i+1].r - c ;
            p[i].a = this.circleTangents(x1, y1, p[i-1].r, x2, y1, p[i+1].r);
            x1 += p[i - 1].r + c + p[i].r;
            this.pix.chain.push(i);
        }
        p[i].pp = [x1, y1];
        x1 += p[i].r + c;
    }
    document.getElementById('tps_e').value = p[--i].tps;
};

/*
 *
 * @a   Arrangement
 * @tb  Teeth O wheel
 * @tm  Teeth o wheel
 * @ts  Teeth * wheel
 * @tps Teeth per second leftmost wheel
 * */
CW.build = function(a, tb, tm, ts, tps) {
    var i, w, c,
        rb, rm, rs, // Radius
        ob, om, os, // Odd/even flag
        sp = null,  // Speed
        pr = '',    // Previous
        th,         // theta
        hor = 0,    // If last wheel has right most tooth horizontal.
        xcw;        // Axel / Chain base width.

    if (a.match(/^[=-]|[=-]$|-=|=-/))
        return 1;
    clearInterval(this.iv);
    this.tsp    = null;
    this.parts  = [];
    this.pix    = {wheel:[],axle:[],chain:[]};
    this.imgm   = 0;
    //this.ctx.clearRect(0, 0, this.can.width, this.can.height);
    this.can.width = this.can.width;

    this.spk    = parseInt(document.getElementById('spikes').value);
    this.tw     = parseFloat(document.getElementById('teeth_w').value);

    if (!isNumbers([tb, tm, ts, tps, this.tw, this.spk]))
        return 1;
    if (tb < 1 || tm < 1 || ts < 1 /*|| tps === 0*/ || this.tw <= 0)
        return 1;

    this.tl     = this.tw + 2;
    this.navcr  = this.tl * 1.5;
    xcw         = this.tl * 2;

    this.sz.rb = rb = this.tw * tb / PI;
    this.sz.rm = rm = this.tw * tm / PI;
    this.sz.rs = rs = this.tw * ts / PI;

    // Biggest radius
    this.br = rb > rm ? rb : rm;
    if (rs > this.br)
        this.br = rs;

    ob = tb % 2;
    om = tm % 2;
    os = ts % 2;

    // Offset x:left, y:center first wheel
    this.ofs = {
        x: this.tl * 3,
        y: /*this.br +*/ 50
    };
    // Repaint rectangle
    this.grect = {
        w: this.ofs.x,
        h: this.br * 2 + 100
    };

    this.dir  = tps > 0 ? 1 : -1;
    tps = Math.abs(tps);
    this.last = null;

    for (i = 0; i < a.length; ++i) {
        th = 0;
        switch ((c = a.charAt(i))) {
        case 'O':
            if (sp === null) {
                sp = (P2 / tb) * tps;
            } else if (pr === 'o') {
                sp = sp / rb * rm;
            } else if (pr === '*') {
                sp = sp / rb * rs;
            }
            // ODD + HOR = no skew
            // If odd result is skew
            if ((hor && ob) || (!hor && !ob)) {
                hor = 1;
            } else {
                th = this.tw / rb;
                hor = 0;
            }
            this.add({type:'wheel', rad:rb, teeth:tb, speed:sp, theta:th});
            break;
        case 'o':
            if (sp === null) {
                sp = (P2 / tm) * tps;
            } if (pr === 'O') {
                sp = sp / rm * rb;
            } else if (pr === '*') {
                sp = sp / rm * rs;
            }
            if ((hor && om) || (!hor && !om)) {
                hor = 1;
            } else {
                th = this.tw / rm;
                hor = 0;
            }
            this.add({type:'wheel', rad:rm, teeth:tm, speed:sp, theta:th});
            break;
        case '*':
            if (sp === null) {
                sp = (P2 / ts) * tps;
            } if (pr === 'O') {
                sp = sp / rs * rb;
            } else if (pr === 'o') {
                sp = sp / rs * rm;
            }
            if ((hor && os) || (!hor && !os)) {
                hor = 1;
            } else {
                th = this.tw / rs;
                hor = 0;
            }
            this.add({type:'wheel', rad:rs, teeth:ts, speed:sp, theta:th});
            break;
        case '-':
            for (w = 1; a.charAt(i + 1) === '-'; ++i, ++w)
                ;
            this.add({type:'axle', rad:w * xcw, speed:sp, theta:th});
            hor = 1;
            break;
        case '=':
            for (w = 1; a.charAt(i + 1) === '='; ++i, ++w)
                ;
            this.add({type:'chain', rad: w * xcw, speed:sp, theta:th});
            hor = 1;
            break;
        default:
            this.parts = [];
            return 1;
        }
        if (c !== '=')
            pr = a.charAt(i);
    }
    if (!this.parts.length)
        return 1;
    // Hack to prevent stray borders in page.
    this.can.style.display = 'none';
    this.can.width = this.can.width + 50;

    this.can.width  = this.grect.w;
    this.can.height = this.grect.h + 50;
    this.can.style.display = 'block';

    this.postBuild();
    if (this.shade) {
        //this.setShadow({x:-1,y:1,b:13});
        this.setShadow({c:"0,0,0,.6", x:-4, y:4, b:13});
        this.setShadow({c:"0,0,0,.8", x:0, y:0, b:this.tw*2});
        //this.ctx.shadowBlur = 17;
    } else {
        this.ctx.shadowBlur = 0;
    }
    this.genStatic();
    this.step();
};

/*
 * Runtime functions.
 *
 * * */
CW.tick = function(tt) {
    this.ctx.clearRect(0, 0, this.grect.w, this.grect.h);
    this.noShadow();
    this.ctx.textAlign = "left";
    this.ctx.fillText("F: " + tt, 15, 15);
    this.ctx.textAlign = "center";
    if (this.shade) {
        this.setShadow({c:"0,0,0,.8",x:0,y:0,b:this.tw*2});
    }
    this.drawStatic();
    this.drawAnim(tt);
};

CW.step = function () {
    if (this.parts.length)
        this.tick((1/this.fps).toFixed(3));
};

CW.run_raf = function(ts) {
    if (this.tsp === null) {
        this.tsp = ts;
    }
    this.tsp = ts - this.tsp;
    this.tick(this.tsp/1000);
    requestAnimationFrame(this.run.bind(this));
    this.tsp = ts;
};

CW.run_iv = function() {
    var ts, that = this, ic = this.fps;
    this.tsp = +Date.now();
    this.iv = setInterval(function() {
        ts  = +Date.now() - that.tsp;
        that.tsp = +Date.now();
        that.tick(ts/1000);
        if (ic !== that.fps) {
            clearInterval(that.iv);
            that.run_iv();
        }
    }, 1000 / this.fps);
};

CW.stop = function () {
    clearInterval(this.iv);
    this.mode = 0;
};

CW.run = function () {
    this.stop();
    if (!this.parts.length)
        return this.ui_build_run;
    this.mode = 1;
    this.raf = !document.getElementById('run_iv').checked;
    if (this.raf)
        requestAnimationFrame(this.run_raf.bind(this));
    else
        this.run_iv();
};

/*
 * UI functions
 *
 * * */
CW.ui_build = function() {
    if (this.build(
        document.getElementById('arr').value,
        +document.getElementById('teeth_b').value,
        +document.getElementById('teeth_m').value,
        +document.getElementById('teeth_s').value,
        +document.getElementById('tps_1').value
    ))
        return 1;
};

CW.ui_build_run = function() {
    if (this.ui_build())
        return 1;
    if (this.mode > 0)
        this.run();
};

/*
 * This should have been refactored.
 * * */
CW.ui_init = function() {
    var i, cw = this,
    e   = document.getElementById('fps'),
    fv  = document.getElementById('fpsv'),
    dv  = document.getElementById('decorv');

    this.fps = +e.value;
    fv.innerHTML = this.fps.toFixed(1);
    e.addEventListener('change', function(e) {
        cw.fps = parseFloat(e.target.value);
        fv.innerHTML = cw.fps.toFixed(1);
    });

    e  = document.getElementById('decor');
    this.decor = +e.value;
    dv.innerHTML = this.decor;
    e.addEventListener('change', function(e) {
        cw.decor = parseInt(e.target.value);
        dv.innerHTML = cw.decor;
        cw.ui_build_run();
    });

    e  = document.getElementById('pin');
    this.pin = !!e.checked;
    e.addEventListener('change', function(e) {
        cw.pin = e.target.checked;
        cw.ui_build_run();
    });
    e  = document.getElementById('shadow');
    this.shade = !!e.checked;
    e.addEventListener('change', function(e) {
        cw.shade = e.target.checked;
        cw.ui_build_run();
    });

    e  = document.getElementById('shwheel');
    this.shwheel = !!e.checked;
    e.addEventListener('change', function(e) {
        cw.shwheel = e.target.checked;
        cw.ui_build_run();
    });

    e  = document.getElementById('star');
    this.star = !!e.checked;
    e.addEventListener('change', function(e) {
        cw.star = e.target.checked;
        cw.ui_build_run();
    });

    e = document.getElementById('run_iv');
    cw.raf = !e.checked;

    document.getElementById('build').addEventListener(
        'click', cw.ui_build.bind(cw));
    document.getElementById('stop').addEventListener(
        'click', cw.stop.bind(cw));
    document.getElementById('step').addEventListener(
        'click', cw.step.bind(cw));
    document.getElementById('run').addEventListener(
        'click', cw.run.bind(cw));

    e = document.getElementsByTagName('INPUT');
    for (i = 0; i < e.length; ++i) {
        if (e[i].type === 'text') {
            e[i].addEventListener('keyup', cw.ui_build_run.bind(cw));
        } else if (e[i].type === 'radio') {
            e[i].addEventListener('change', cw.ui_build_run.bind(cw));
        }
    }
};

document.addEventListener("DOMContentLoaded", function () {
    var cw = new CogWheels();
    cw.ui_init();
    cw.ui_build_run();
});

```

# Answer
> 3 votes
# Julia

```
chain(s) = all((c)->c=='=',s)
axle(s) = all((c)->c=='-',s)
direct(s) = s==""

function mechanical(arrangment,O,o,x,speed_l)
    teeth = {"O"=>O, "o"=>o, "*"=>x}
    process(c) = direct(c[2]) ? -1 : chain(c[2]) ? 1 : axle(c[2]) ? teeth[c[3]]/teeth[c[1]] : 0
    matches = collect(eachmatch(r"([Oo*])([-=]*)([Oo*])",arrangment,true))
    length(matches) == 0 ? 0 : speed_l*prod([process(m.captures) for m in matches])
end

# test cases
println(mechanical("*-Oo-O",50,30,10,3))
println(mechanical("o*-O*= =oO",50,30,10,-3))
println(mechanical("O---*oO=O*-oo",15,12,8,10))
println(mechanical("O *",50,30,10,10))

```

Gives correct output. `r"stuff"` is a regex.

# Answer
> 2 votes
# Java

```
import java.util.Scanner;

/**
 *
 * @author Quincunx
 */
public class MechanicalCoding {
    final static int[] teeth = new int[3];

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        System.out.println("Input the arrangement:");
        String layout = scan.nextLine();

        System.out.println("Input the:");
        System.out.print("\tNumber of teeth on large gear:\n\t");
        teeth[2] = scan.nextInt();
        scan.nextLine();
        System.out.print("\tNumber of teeth on medium gear:\n\t");
        teeth[1] = scan.nextInt();
        scan.nextLine();
        System.out.print("\tNumber of teeth on small gear:\n\t");
        teeth[0] = scan.nextInt();
        scan.nextLine();

        System.out.println("Input the speed of the left hand side:");
        double speed = scan.nextDouble();

        layout = layout.replaceAll("([-=])+", "$1");

        char lastC = ' ';
        boolean mustBeNext = false;
        for (char c : layout.toCharArray()){
            switch (c){
                case 'O':
                case 'o':
                case '*':
                    if (lastC == '=' || lastC == ' '){
                        break;
                    }
                    if (lastC == '-'){
                        speed *= 1.*teeth(c)/teeth(lastC);
                        break;
                    }
                    speed *= -1;
                    break;
                case '-':
                case '=':
                default:
                    if (lastC == ' '){
                        System.exit(1);
                    }
            }
            lastC = c;
        }
        if (lastC == '-' || lastC == '='){
            System.exit(1);
        }
        System.out.println(speed);
    }
    public static int teeth(char c){
        return teeth[c=='O'?2:c=='o'?1:0];
    }
}

```

What a relief to be able to use Java! Sample run:

```
Input the arrangement:
o*-O*==oO
Input the:
    Number of teeth on large gear:
    50
    Number of teeth on medium gear:
    30
    Number of teeth on small gear:
    10
Input the speed of the left hand side:
-3.0
15.0

```

# Answer
> 1 votes
## C#, 396 bytes

Golfed for fun with added indentation. I'm sure the same code would be smaller in a loosely-typed language.

```
namespace System.Text.RegularExpressions{
    class P{
        static void Main(string[]a){
            var s=Regex.IsMatch(a[0],"^[-=]|[-=]$|-=|=-|[^-=Oo*]")?0:double.Parse(a[4]);
            foreach(Match m in Regex.Matches(a[0],"[Oo*]{2,}"))
                s*=m.Length%2*2-1;
            foreach(Match m in Regex.Matches(a[0],"[Oo*]-+[Oo*]"))
                s*=double.Parse(a[" Oo*".IndexOf(m.Value[m.Length-1])])/double.Parse(a[" Oo*".IndexOf(m.Value[0])]);
            Console.Write(s);
        }
    }
}

```

# Answer
> 1 votes
# 159 Bytes - Javascript

This uses ECMAScript 6 Features so will only work in browsers that support those - Firefox is one.

```
(g,l,m,s,v,n)=>{for(a={'O':l,'o':m,'*':s};n!=g&&(n=g);g=g.replace(/[Oo*](-*|=*)([Oo*])/,(w,y,z)=>((v*=y?(y[0]=='='?1:a[z]/a[w[0]]):-1)-v)||z));return a[g]?v:0}

```

Defines an anonymous function that takes the parameters `arrangement O o * speed` and returns the speed of the last cog for a valid arrangement, and zero otherwise.

Can test all test cases in firefox with:

```
[((g,l,m,s,v,n)=>{for(a={'O':l,'o':m,'*':s};n!=g&&(n=g);g=g.replace(/[Oo*](-*|=*)([Oo*])/,(w,y,z)=>((v*=y?(y[0]=='='?1:a[z]/a[w[0]]):-1)-v)||z));return a[g]?v:0}).apply(0,a) for each (a in [['*-Oo-O',50,30,10,3],['o*-O*==oO',50,30,10,-3],['O---*oO=O*-oo',15,12,8,10],['=o*',50,30,10,-3],['o*-',50,30,10,-3],['o-=*',50,30,10,-3],['o *',50,30,10,-3]])]

```

---
Tags: popularity-contest, parsing
---


title: Interactive Lights Off game

text:
# Question
Title: Interactive Lights Off game
## Intro

I guess most people are familiar with the game Lights Off, but in case someone isn't, here is a short description:

> You start with an NxN grid where each cell in the grid is a light. For this example N=5. There are 2 ways the game can start: either all of the lights are on, or some lights are off. The goal is to turn off all of the lights. If you toggle a light, the lights left, right, above and below it will toggle with it.

### All Lights on

```
O O O O O
O O O O O
O O O O O
O O O O O
O O O O O

```

### Toggled cells

```
Toggled(0,0) | Toggled(1,2)| Toggled(2,4)
X X O O O    |  O O X O O  |  O O O O O
X O O O O    |  O X X X O  |  O O O O X
O O O O O    |  O O X O O  |  O O O X X
O O O O O    |  O O O O O  |  O O O O X
O O O O O    |  O O O O O  |  O O O O O

```

## Task

Make an interactive game of Lights Off with as little code as possible.

**Requirements**

There is a setup phase and a play phase.

The setup phase takes user input to determine the grid size (minimum size of 5) and whether the grid starts with all of the lights on. If the grid should not start with all of the lights on, lights must be selected randomly to start off: at least 1 and at most 20% of the lights.

In the play phase, the grid is displayed to the user and moves are taken as input. The application could use a windowed GUI with lights toggled by clicking, or a text UI which takes typed input of the coordinates of the cell to toggle.

When the user reaches a solved state (all lights off), the application must notify them that they have solved the puzzle, and show how many moves it took.

The use of external resources is not allowed.

If there is anything unclear or missing please let me know :)

### Related questions

# Answer
## APL (101)

```
00{⎕←'XO'[1+⍵]⋄1∨.=,⍵:(⍺+1)∇⍵≠(⍳⍴⍵)∊⎕∘+¨Z,⌽¨Z←0∘.,¯1 0 1⋄'SOLVED',⍺}⎕{⍺:⍵ ⍵⍴1⋄~(⍵ ⍵⍴⍳V)∊V?⍨⌊.2×V←⍵*2}⎕

```

The first input is the size, the second input is the start value (0=some off, 1=on). Coordinates are 1-based.

```
      0{⎕←'XO'[1+⍵]⋄1∨.=,⍵:(⍺+1)∇⍵≠(⍳⍴⍵)∊⎕∘+¨Z,⌽¨Z←0∘.,¯1 0 1⋄'SOLVED',⍺}⎕{⍺:⍵ ⍵⍴1⋄~(⍵ ⍵⍴⍳V)∊V?⍨⌊.2×V←⍵*2}⎕
⎕:
      5
⎕:
      1
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
⎕:
      2 2
OXOOO
XXXOO
OXOOO
OOOOO
OOOOO
⎕:

```
> 3 votes

# Answer
## C++, 564 bytes

```
#include <iostream>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <vector>
using namespace std;int main(){int n,p,s=0,y,i=0,b;cin>>n>>b;if(n<5)n=5;vector<int>m(n*n,1);srand(time(0));if(b)for(int&c:m)c=rand()<RAND_MAX/6;for(;i<n*n;i++)cout<<m[i]<<(-~i%n?"":"\n");while(find(m.begin(),m.end(),1)!=m.end()){cin>>p>>y;p+=y*n;if(p<0||p>=n*n)continue;m[p]=!m[p];if(p%n)m[p-1]=!m[p-1];if(p%n+1<n)m[p+1]=!m[p+1];if(p>=n)m[p-n]=!m[p-n];if(p+n<n*n)m[p+n]=!m[p+n];for(i=0;i<n*n;i++)cout<<m[i]<<(-~i%n?"":"\n");s++;}cout<<"Solved in "<<s<<" steps."<<endl;}

```

In setup phase, the user should input the grid size first. Then if the grid should starts with all of the lights on, the user should input `0`; otherwise `1`.

In play phase, the user should input the 0-based coordinates of the cell to toggle until all lights off.

Original code:

```
#include <iostream>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <vector>
using namespace std;
int main() {
    int n, p, s = 0, y, i = 0, b;
    cin >> n >> b;
    if(n < 5) n = 5;
    vector<int> m(n * n, 1);
    srand(time(0));
    if (b) for (int& c : m) c = rand() < RAND_MAX / 6;
    for (; i < n * n; i++) cout << m[i] << (-~i % n ? "" : "\n");
    while (find(m.begin(), m.end(), 1) != m.end()) {
        cin >> p >> y;
        p += y * n;
        if (p < 0 || p >= n * n) continue;
        m[p] = !m[p];
        if (p % n) m[p - 1] = !m[p - 1];
        if (p % n + 1 < n) m[p + 1] = !m[p + 1];
        if (p >= n) m[p - n] = !m[p - n];
        if (p + n < n * n) m[p + n] = !m[p + n];
        for (i = 0; i < n * n; i++) cout << m[i] << (-~i % n ? "" : "\n");
        s++;
    }
    cout << "Solved in " << s << " steps." << endl;
}

```
> 3 votes

# Answer
# C - 365 characters

```
#define a for(y=0;y<w*w;y++)
*k,i,w,x,y,c=0;main(){scanf("%i %i",&w,&i);k=malloc(4*w*w+8*w)+4*w;i&=1;srand(k);a k[y]=i||ra
nd()<6553;i^=1;for(;;){x=0;a{putchar(k[y]?79:88);x|=k[y]!=i;!((y+1)%w)&&putchar(10);}if(!x&&c
)return printf("won in %i",c);putchar(62);scanf("%i %i",&x,&y);k[x*w-w+y]^=x>0;k[x*w+y-1]^=y>
0;k[x*w+w+y]^=x<w-1;k[x*w+y+1]^=y<w-1;k[x*w+y]^=1;c++;}}

```

In setup phase, it asks the user for two integers: table size and starting state (`0` for off and `1` for on), respectively.

After that, before every move, it will print the grid, then prompt (`>`) the user for 0-based xy coordinates of the point.
> 3 votes

---
Tags: code-golf
---