text:
Let's do the Wave!
Input:

A string (the wave-snippet) with a length >= 2.
A positive integer n >= 1.

Output:
We output a single-line wave. We do this by repeating the input string n times.
Challenge rules:

If the first and last character of the input string matches, we only output it once in the total output (i.e. ^_^ of length 2 becomes ^_^_^ and not ^_^^_^).
The input string won't contain any whitespaces/tabs/new-lines/etc.
If your language doesn't support non-ASCII characters, then that's fine. As long as it still complies to the challenge with ASCII-only wave-input.

General rules:

This is code-golf, so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters, full programs. Your call.
Default Loopholes are forbidden.
If possible, please add a link with a test for your code.
Also, please add an explanation if necessary.

Test cases:
_.~"(              length 12
_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(

'°º¤o,¸¸,o¤º°'     length 3
'°º¤o,¸¸,o¤º°'°º¤o,¸¸,o¤º°'°º¤o,¸¸,o¤º°'

-__                length 1
-__

-__                length 8
-__-__-__-__-__-__-__-__

-__-               length 8
-__-__-__-__-__-__-__-__-

¯`·.¸¸.·´¯         length 24
¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯

**                 length 6
*******

String & length of your own choice (be creative!)

It would be nice to add snippet with results into the question :)

"A positive integer n >= 1" seems kinda pleonastic to me... :)

Pyke, 15 14 10 bytes
tQQhQeq>*+

Try it here!
  QhQeq    -    input_1[0] == input_1[-1]
 Q     >   -   input_1[^:]
        *  -  ^ * V
t          -   input_2 - 1
         + - input_1 + ^

+1 for an explanation that looks like a wave itself!

Python 3, 32 bytes
lambda s,n:s+s[s[0]==s[-1]:]*~-n

Concatenates n copies of the string, removing the first character from all copies but the first if the first character matches the last one.

This doesn't properly handle the question's "¯`·.¸¸.·´¯" string, does it? When I try it, s[0] and s[-1] seem to refer to the first and last byte, rather than the first and last character. Edit: ah, wait, that's Python 2 vs. Python 3. It works correctly in Python 3.

05AB1E, 13 bytes
Uses CP-1252 encoding.
D¬U¤XQi¦}I<×J

Try it online!
Explanation
-___- and 3 used as input for example.
D              # duplicate input string
               # STACK: "-___-", "-___-"
 ¬U¤X          # push copies of the first and last element of the string
               # STACK: "-___-", "-___-", "-", "-"
     Q         # compare for equality
               # STACK: "-___-", "-___-", 1
      i¦}      # if true, remove the first char of the copy of the input string
               # STACK: "-___-", "___-"
         I<    # push input number and decrease by 1
               # STACK: "-___-", "___-", 2
           ×   # repeat the top string this many times
               # STACK: "-___-", "___-___-"
            J  # join with input string
               # STACK: "-___-___-___-"
               # implicitly output

JavaScript (ES6), 47 bytes

f=
(s,n)=>s+s.slice(s[0]==s.slice(-1)).repeat(n-1)
;

<input id=s><input id=n type=number min=1>

Congrats on 20k!

@Adnan Thanks! 20002 too, which is nice and symmetrical.

Is currying possible in this instance? I mean doing s=>n=>... instead of (s,n)=>

Perl, 29 bytes
28 bytes code + 1 for -p.
Thanks to @Dada for helping me shave off a few bytes!
s/^((.).*?)(\2?)$/$1x<>.$3/e

Usage
perl -pe 's/^((.).*?)(\2?)$/$1x<>.$3/e' <<< "'°º¤o,¸¸,o¤º°'
3"
'°º¤o,¸¸,o¤º°'°º¤o,¸¸,o¤º°'°º¤o,¸¸,o¤º°'
perl -pe 's/^((.).*?)(\2?)$/$1x<>.$3/e' <<< '**
6'
*******

Online example.

Nice. You could save (indirectly) 3 bytes by using <> instead of $' as it allows you to get rid of -0. And then you can use s///e instead of //;$_= to win one more byte :-)

@Dada nice... I completely screwed up my original attempt and oversimplified it and ended up making it much larger... I've taken your comments on board but I seem to need a $ to match the end, still saves me bytes as not using ' means I can drop it having to be save to a file to save adding 3 for -p and drop it back to 1!

Huhu. Yes indeed it needs the $ instead of the newline you previously had. (Sorry my comment wasn't very detailed, I was in a hurry...)

I like the idea of using <> in the replace string. But if n is separated by a space instead of a newline, the character count can be reduced a bit: s/(.+?) (\d+)/$1x$2/e

@squeamishossifrage I've had a little play, but I can't find a way to omit the first char if it's repeated at the end that way, closest I got was 33 s/^((.).*?)(\2?) (.+)/$1x$4.$3/e unless I'm missing something... (end of my working week so I'm lacking in brainpower!)

@DomHastings Ah, my mistake. Didn't read the question properly :-)

Perl, 23 bytes
Includes +1 for -p
Give input string followed by number on separate lines on STDIN
wave.pl <<< "'°º¤o,¸¸,o¤º°'
3"

wave.pl:
#!/usr/bin/perl -p
$_ x=<>;s/(.)\K
\1?//g

If the first character in the word is not a regex special character this 22 bytes version works too:
#!/usr/bin/perl -p
$_ x=<>;/./;s/
$&?//g

Neat! I think you forgot the /g modifier when you pasted it though ;-)

@Dada Oops. Fixed

Retina, 29 bytes
Lines 2 and 5 have a trailing space.
 .+
$*
 $

 $`
(.) +\1?
$1

Try it online! (The first line enables a linefeed-separated test suite.)

Batch, 117 bytes
@set/ps=
@set t=%s%
@if %s:~0,1%==%s:~1% set t=%s:~1%
@for /l %%i in (2,1,%1)do @call set s=%%s%%%%t%%
@echo %s%

Takes the number of repetitions as a command-line parameter and reads the string from STDIN.

MATL, 19 17 14 bytes
ttP=l):&)liX"h

This works for ASCII on the online interpreter and for both unicode and ASCII when run using MATLAB.
Try it Online!
Explanation
        % Implicitly grab the input as a string
        %   STACK:  {'abcdea'}
        %
tt      % Make two copies and push them to the stack
        %   STACK:  {'abcdea'    'abcdea'    'abcdea'}
        %
P       % Flip the second copy around
        %   STACK:  {'abcdea'    'abcdea'    'aedcba'}
        %
=       % Perform an element-wise comparison. Creates a boolean array
        %   STACK:  {'abcdea'    [1 0 0 0 1]}
        %
l)      % Get the first element. If the first and last char are the same this will be
        % TRUE (1), otherwise FALSE (0)
        %   STACK:  {'abcdea'    1 }
        %
:       % Create an array from [1...previous result]. If the first char was repeated,
        % this results in the scalar 1, otherwise it results in an empty array: []
        %   STACK: {'abcdea'    1 }
        %
&)      % Break the string into pieces using this index. If there were repeated
        % characters, this pops off the first char, otherwise it pops off
        % an empty string
        %   STACK: {'a'    'bcdea'}
        %
li      % Push the number 1 and explicitly grab the second input argument
        %   STACK: {'a'    'bcdea'    1    3}
        %
X"      % Repeat the second string this many times
        %   STACK: {'a'    'bcdeabcdeabcdea'}
        %
h       % Horizontally concatenate the first char (in case of repeat)
        % or empty string (if no repeat) with the repeated string
        %   STACK: {'abcdeabcdeabcdea'}
        %
        % Implicitly display the result

Pyth, 13 bytes
+z*@tBzqhzezt

Test suite!
Explanation to follow.

Gema, 41 characters
* *=@subst{\? \$1=\?\; =;@repeat{$2;$1 }}

Sample run:
bash-4.3$ gema '* *=@subst{\? \$1=\?\; =;@repeat{$2;$1 }}' <<< '_.~"( 12'
_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(

bash-4.3$ gema '* *=@subst{\? \$1=\?\; =;@repeat{$2;$1 }}' <<< "'°º¤o,¸¸,o¤º°' 3"
'°º¤o,¸¸,o¤º°'°º¤o,¸¸,o¤º°'°º¤o,¸¸,o¤º°'

bash-4.3$ gema '* *=@subst{\? \$1=\?\; =;@repeat{$2;$1 }}' <<< '** 6'
*******

PowerShell v2+, 48 bytes
Param($s,$n)$s+$s.Substring($s[0]-eq$s[-1])*--$n

Outputs the whole string once, followed by n-1 copies of the string or substring, depending on if the first and last characters match.
The .Substring() method outputs from the index supplied to the end of the string, so if $s[0]-eq$s[-1] evaluates to false (0), we get the whole string. If that statement is true (1), We get the substring starting at the second character.

Dangit, ya beat me by a few minutes. I had the same answer (using $a and $b instead of $s and $n).

K, 12 Bytes
{,/[y#(,)x]}

/in action
{,/[y#(,)x]}["lollol";4]
"lollollollollollollollol"
{,/[y#(,)x]}["-_";10]
"-_-_-_-_-_-_-_-_-_-_"

/explanation (read function from right to left)
x is the string and y is the number of repetitions
(,)y    --enlist x so it becomes 1 value (rather than a list)
y#x     --take y many items of x
,/      --coalesce the list ,/[("-_";"-_")] --> "-_-_"

Thanks

This breaks Rule 1. {,/y#,$[(*x)~*|x;-1;0]_x} for 25 bytes handles first/last matching. If you're happy breaking Rule 1, then you can have {,/y#,x} for 8.

VBA 119 bytes
New to this game and vba wins with the highest bytes :P
PS: can't believe vba stands close to JAVA HAHA
Function l(s,x)
l=s: s=IIf(Left(s,1)=Right(s,1),Mid(s,2,Len(s)),s)
z: x=x-1: If x>0 Then l=l & s: GoTo z:
End Function

Explanation:
+------------------------------------------------------------+-----------------------------------------------------------------------------------+
|                            code                            |                                     function                                      |
+------------------------------------------------------------+-----------------------------------------------------------------------------------+
| l=s                                                        | input string s is saved to base                                                   |
| s = IIf(Left(s, 1) = Right(s, 1), Right(s, Len(s) - 1), s) | checks whether 1 and last char is equal,                                          |
|                                                            | if yes removes the first char from s and that s will be used to for further joins |
| z:                                                         | z: is a label                                                                     |
| x = x - 1:                                                 | decreases looping round                                                           |
| If x > 0 Then l = l & s: GoTo z:                           | join strings until no more rounds to do                                           |
+------------------------------------------------------------+-----------------------------------------------------------------------------------+

Welcome to PPCG! As a QBasic programmer myself, I would say that you can remove most of the spaces and still have valid VBA code, since you can type or paste the shortened code (with the autoformatter adding the spaces), hit run, and it works. That would improve your score considerably. :)

Java 11, 123 111 109 107 102 100 79 58 bytes
s->n->s+s.substring(s.matches("(.).*\\1")?1:0).repeat(n-1)

Try it online.
I'll of course try to answer my own question. ;)
-5 bytes thanks to @dpa97.
-21 bytes converting from Java 7 to 10.
-21 bytes converting from Java 10 to 11.
Explanation:
s->n->             // Method with String & integer parameters and String return-type
  s                //  Return the input-String as result
   +               //  Appended with:
    s.subtring(    //   A substring of the input-String:
      s.matches("(.).*\\1")?
                   //    If the first and last characters are the same:
       1           //     Remove the first character in the substring-call
      :            //    Else:
       0)          //     Use the input-String as is
     .repeat(n-1)  //   Repeated the input-integer minus 1 amount of times

s.split("^.")[1]
instead of
s.replaceAll("^.", "")
should work, save a couple bytes

@dpa97 Thanks! I've edited it. I always forget about utilizing .split.

@dpa97 I think I've (or we've) been overthinking it.. s.substring(1) is two bytes shorter. ;)

@KevinCurijssen yeah should have seen that, good find. I think I was stuck on the idea of using regex...

PHP, 72 Bytes
<?=($a=$argv[1]).str_repeat(substr($a,$a[0]==substr($a,-1)),$argv[2]-1);

with PHP 7.1 it could be reduce to 65 Bytes
<?=($a=$argv[1]).str_repeat(substr($a,$a[0]==$a[-1]),$argv[2]-1);

CJam, 16 15 bytes
l]li*{(s@)@|@}*

Try it online
Explanation:
l]li*            Create a list of n-times the input string.
{(s@)@|@}*       Fold this list by taking out the last character of the first
                 argument and the first character of the second argument and
                 replacing them by their unique set union.
                 e.g.: "aba" "aba" -> "ab" 'a"a"| "ba" -> "ab" "a" "ba"
                       "abc" "abc" -> "ab" 'c"a"| "bc" -> "ab" "ca" "bc

I like your wave-input. :)

Pip, 18 bytes
Regex solution, taking advantage of the "no spaces in input" rule. Takes the string from stdin and the number as a command-line argument.
(q.s)XaR`(.) \1?`B

Try it online!
Explanation:
 q.s                Read from stdin and append a space
(   )Xa             String-multiply by first cmdline arg
       R            Replace
        `(.) \1?`     Regex: char followed by space followed by (optional) same char again
                 B    Callback function, short for {b}: return 1st capturing group

Thus, a b turns into ab, a a turns into a, and the space at the end of the string is removed. Then the result is autoprinted.

Haskell, 59 bytes
a%b=concat$replicate a b
a@(s:z)#n|s/=last z=n%a|1<2=s:n%z

Ungolfed version:
-- Helper: Appends str to itself n times
n % str = concat (replicate n str)

-- Wave creating function
(x:xs) # n
 -- If start and end of wave differ,
 | x /= last xs = n%(x:xs)
 | otherwise   = x:(n%xs)

Common Lisp (LispWorks), 176 bytes
(defun f(s pos)(if(equal(elt s 0)(elt s #1=(1-(length s))))(let((s1(subseq s 0 1))(s2(subseq s 0 #1#)))(dotimes(j pos)(format t s2))(format t s1))(dotimes(j pos)(format t s))))

Usage:
    CL-USER 130 > (f "_.~~\"(" 12)
    _.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(
    NIL

    CL-USER 131 > (f "'°o¤o,??,o¤o°'" 3)
    '°o¤o,??,o¤o°'°o¤o,??,o¤o°'°o¤o,??,o¤o°'
    NIL

    CL-USER 132 > (f "-__" 1)
    -__
    NIL

    CL-USER 133 > (f "-__" 8)
    -__-__-__-__-__-__-__-__
    NIL

    CL-USER 134 > (f "ˉ`·.??.·′ˉ" 24)
    ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ`·.??.·′ˉ
    NIL

    CL-USER 135 > (f "**" 6)
    *******
    NIL

Explanation:
~~ =>   ~

\" =>   "

Ungolf:
    (defun f (s pos)
      (if (equal (elt s 0) (elt s (1- (length s))))
          (let ((s1 (subseq s 0 1)) (s2 (subseq s 0 (1- (length s)))))
            (dotimes (j pos)
              (format t s2))
            (format t s1))
        (dotimes (i pos)
          (format t s))))

Vim, 17 bytes
The easy way to do this is to use a back-reference regex that can tell if the first and last chars match. But long regexes are long. We don't want that.
lDg*p^v$?<C-P>$<CR>hd@aP

The wave to repeat is in the buffer. I'm assuming the number to be repeated is in the register "a (type qaNq with N as the number to set it up). The idea is:

If the first and last bytes match, delete everything up to the last character.
If the first and last bytes don't match, delete all the characters.

Then P the deleted text @a times.

lDg*: This maneuver creates a regex that matches any first character, regardless of whether it needs to be escaped or not, or whether it's a word or not. (* would be enough to make the properly escaped regex, but would add unwanted \<\> garbage if it was a word character, like _.)
p^: Last step was messy. Clean up to the original position, beginning of the line.
v$: In visual mode, $ by default moves to after the end of the line.
?<C-P>$<CR>hd: If the previous regex exists at the end of the line, this search will move to it; otherwise, stay beyond the end of the line. Move left from there and we accomplish the (tedious) delete we need.
@aP: Run the number repeat as a macro to be used as an argument to P.

Ruby, 38 bytes
->s,n{s[0]==s[-1]?s[0..-2]*n+s[0]:s*n}

I think this is pretty self-explanatory. I'm still wondering if there's a more concise way to represent the s[0..-2] block, but I haven't found it yet.

Javascript ES6, 49 chars
(s,n)=>s.replace(/(.).*?(?=\1?$)/,m=>m.repeat(n))

Test:

f=(s,n)=>s.replace(/(.).*?(?=\1?$)/,m=>m.repeat(n))
console.log(document.querySelector("pre").textContent.split(`
`).map(s=>s.split` `).every(([s,n,k])=>f(s,n)==k))

_.~"( 12 _.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(_.~"(
'°º¤o,¸¸,o¤º°' 3 '°º¤o,¸¸,o¤º°'°º¤o,¸¸,o¤º°'°º¤o,¸¸,o¤º°'
-__ 1 -__
-__ 8 -__-__-__-__-__-__-__-__
-__- 8 -__-__-__-__-__-__-__-__-
¯`·.¸¸.·´¯ 24 ¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯
** 6 *******

QBIC, 65 bytes
;:~left$$|(A,1)=right$$|(A,1)|A=left$$|(A,len(A)-1)][1,a|B=B+A]?B

I guess I should add LEFT$ and RIGHT$ to QBIC...
Explanation:
;          make the first cmd line parameter into A$
:          make the second cmd line parameter into a (num)
~left..]   Drop the last char if equal to the first char
[1,a...]   FOR the given number of repetitions, concat A$ to B$ (starts out empty)
?B         print B$

C#, 79 bytes
(s,n)=>s+new string('x',n-1).Replace("x",s[0]==s[s.Length-1]?s.Substring(1):s);

A bit of an absurd method of repeating a string. Create a new string of the desired repeat length and then replace each character with the string to repeat. Other than that, looks like pretty much the same strategy as many others.
/*Func<string, int, string> Lambda =*/ (s, n) =>
    s                                      // Start with s to include first char at start
    + new string('x', n - 1).Replace("x",  // Concatenate n-1 strings of...
        s[0] == s[s.Length - 1]            // if first/last char are the same
            ? s.Substring(1)               // then skip the first char for each concat
            : s                            // else concat whole string each time
    )
;

Hmm, what happens if the input string contains a x? Perhaps it would be better to change that into a space, since "The input string won't contain any whitespaces/tabs/new-lines/etc.".

It'll work fine if the input has x. It creates the xx...x string first and then replaces each x without re-evaluating the string from the start with what needs to be replaced.

SpecBAS - 68 bytes
1 INPUT a$,n: l=LEN a$: ?IIF$(a$(1)<>a$(l),a$*n,a$( TO l-1)*n+a$(l))

Uses inline-IF to check if first and last characters are the same.
If not, print string n number of times.
Otherwise, splice the string to length-1, repeat that and put last character at end.
Can only accept ASCII characters (or characters built into SpecBAS IDE)

APL, 19 bytes
{⍺,∊1↓⍵⍴⊂⍺↓⍨⊃⍺=⊃⌽⍺}

Usage:
      '^_^' {⍺,∊1↓⍵⍴⊂⍺↓⍨⊃⍺=⊃⌽⍺} 5
^_^_^_^_^_^

Explanation:

⊃⍺=⊃⌽⍺: see if the first character matches the last character
⍺↓⍨: if this is the case, drop the first character
⊂: enclose the result
⍵⍴: replicate it ⍵ times
1↓: drop the first one (this is shorter than (⍵-1)⍴)
∊: get all the simple elements (undo the boxing)
⍺,: add one instance of the whole string to the front

Postscript, 98 bytes
exch/s exch def/l s length 1 sub def s 0 get s l get eq{/s s 0 l getinterval def}if{s print}repeat

...but you might need a ' flush' tacked onto that to get your PS interpreter to flush the comm buffer, another six bytes :(

Java (117 bytes)
String w(String a,int b){String c=a;for(;b>0;b--)c+=b+a.substring(a.charAt(a.length()-1)==a.charAt(0)?1:0);return c;}

Hi, welcome to PPCG! Hmm, I've posted already a shorter Java 7 answer here. Yours uses an approach similar to the one I had previously. By using this same approach, you could golf b>0;b-- to b-->0;. Also, why is the b+ there at c+=b+a.substring? Still, it's a great first answer if you came up with it independently. Enjoy your stay here on PPCG! :) Also, you might find Tips for golfing in Java interesting to read.


text:
Hurricane Matthew and the Lightning Bolts
Challenge
Inspired by this challenge and the nasty Hurricane Matthew, we will be generating some lightning bolts dynamically.
n = 15:
   \
   /\
  /  \
 /   /
/\  /\
 /  \ \
/   / /\
   /\ \
  / /  \
 /\ \  /\
  /  \ \
 /\  /
   \
    \
    /\

Input
Positive Integer n determines the depth of the lightning round.
Rules and Constraints

/ and \ should be used
The probability guiding the lightning's direction is as follow:

25% Splits into 2 paths
25% Path reaches dead end
25% Goes Left
25% Goes Right
There are a few exceptions regarding overlapping and dead end below:

The code should not be deterministic, a new lightning bolt should be generated randomly every time
The bolts should not overlap: e.g. if there is already a bolt to the left of the current bolt, the current bolt should either end or go right, but not go left or split (probability still applies, in this case it become 50%end/50%right)
If there does not exist another available split path, the path should not end: e.g. in the beginning when there is only 1 path, the path should not end until it splits, also applies when there are multiple paths but all except one path are dead, (probability becomes 33%split/33%left/33%right) your goal is to reach the bottom
Whitespaces can be added on the left (all you would need should only be height-1)
However you want to generate the bolt is up to you, you can go from bottom up, left to right, etc. As long as all the rules above are satisfied

Another example
n = 10
 \
 /
 \
 /\
  /\
 / /
/\ \
 / /\
 \   \
 /

Stay safe and have fun golfing!
Please golf responsibly only when you are in a safe area!!

Stay safe and have fun golfing! Maybe also specify that if EAS strikes, abandon everything and follow orders! Golfing code is not your priority in such a situation.

@EriktheGolfer you are not a true golfer then.

I don't believe that "The center-most path should be the one reaching the ground" is consistent with the rest of the random-generation description. For example, it's randomly possible for the original bolt to split twice and then for the middle two bolts to end; how can this possibility be overridden while still preserving the probabilities indicated?

Also, what happens if (for example) the first two steps are both splits? Then the middle two bolts are touching each other, which seems problematic but also isn't ruled out by the special cases.

@GregMartin Good point on the center-most part, originally I was hoping it to generate a balanced bolt, but now that I think about it even without that constraint about 50% of the time it should end up somewhere in the middle, a depth of 15 would only have 1-2% chance where the right or left most path lands. I'll remove that rule. And for the 2 steps splitting part, the only thing to prevent for is that no 2 paths should 2 paths join: \/ at any point.

Ok on the first choice. But you should specify exactly what probabilities you want to occur to avoid the \/ situation.

@GregMartin  Because the order of the creation of the path is flexible as per last rule, i.e. if you create the left path first, then the left side of the split path would have the full probability 25/25/25/25, but then the right path would be limited to 50right/50end. I suppose one could argue that this would conflict with the original probability distribution, but since that rule is at the lowest priority, we would always want to adhere to these overlapping and dead end rules first if that makes sense.

I'm sure there is a way of phrasing it so that it makes sense. I'm just pointing out that you need to do so :)

Is any amount of whitespace to the left and the right of the bolt allowed ?

@TonHospel The left white spaces should be added such that the line above connects with the next one, however the white spaces to the right are not restricted

@Zukaberg I understand that.  But can I add the same amount of of whitespace in front (and possibly after) every line so that the whole bolt is shifted to the right. This is relevant for a top down construction so the bolt cannot get too wide

@TonHospel I've added a new rule that the left whitespaces (the amount that the whole structure is shifted to the right) must be less than the width of your structure

@Zukaberg That's not very useful since the bolt structure can be only 1 wide if you are (un)lucky. What I'm obviously looking for is starting with as many white spaces as the height of the structure-1

@TonHospel I suppose it would be reasonable to allow that, the challenge's focus is not on this minor detail, if it means better focus on the actual bolt structure sure I don't mind that

Perl, 92 90 89 84 bytes
Includes +1 for -n
Give height on STDIN:
perl -M5.010 bolt.pl <<< 15

bolt.pl:
#!/usr/bin/perl -n
map{$_=$;until$;=$_,s/.6|3.?/53|16*rand/eg,/3|6/>/36/;say y|3615|\\/ |r}(1x$_.6)x$_

Explanation
If you call the offset of the starting point 0 (a point is at the corner of a character box), then on the next row you can have gone left or right (or not) and can end up with points on offsets -1,1. The next row gives -2,0,2 as possible offsets etc. They all differ by 2. If you then call the character to the lower left of a point even and the character to the lower right odd you can extend that to assigning even or odd to each character position on a row such that even and odd alternate (in fact the whole plane is tiled in a checkerboard pattern). An even position can have a / or , an odd position can have \ or .
The character just before a / is in an odd position so it could be either \ or , but \/ is forbidden so only  is possible. Similarly the character after a \ must be a  (assuming the row is padded with enough spaces to the left and the right so the row boundaries are no issue). So a lightning bolt continues on the next row always directly below a \ or below a /. In either case the lower point is in the middle and the next row can have one of , /, \ or /\ directly below the top 2 characters. So to generate the next row I can simply replace any \ or / by any of these 4 expansions with equal probability (you could also independently replace the first character by  or / and the second character by  or \). In perl you could do this with something like:
s#\\ | /#("  "," \\","/ ","/\\")[rand 4]#eg

If the resulting row however contains \/ (forbidden join) or no / or \ at all (bolt dies and does not reach the bottom) the result is invalid. In that case I throw away the whole row and simply try again. A valid continuation always exists and if you try often enough one will be found (e.g everything dies except for 1 flow). This is a slightly different probability distribution from the suggested anti-overlap algorithm, but I think this is in fact better since it has no directional bias. Validity can be testing in a golfish way using
m#\\|/#>m#\\/#

The problem here is that the random substitution is so looooong and all these \ escapes also eat bytes. So I decided to build my rows using strings of digits and replace the appropriate digits by , / and \ just before printing. The basic random replacement is
53|16*rand

which gives one of 53, 55, 61 or 63 with equal probability. I then interpret 5 and 1 as , 3 as \ and 6 as /. That explains the row print:
say y|3615|\\/ |r

In a serious golf competition I would now start to systematically explore alternative magic formulas, but this should be pretty good (within 3 bytes of optimal)
The rest of the components of the program:
1x$_.6

This initializes $_ (see the next map) to height spaces followed by a /. This is an invisible row above the first one being printed and makes sure the field is wide enough so the bolt can never run out of space at the left
map{ ... ; say ...}(1x$_.6)x$_

I will process this same initial string height times printing a new row each time
$_=$;until$;=$_,...

Save the current row in $;. If the replacement turns out to be invalid restore $_ from $;
s/.6|3.?/53|16*rand/eg

Do the actual substitution. I don't have to check what is before / or after \ since it must be a space. This is convenient since space can be represented by either 1 or 5. Since I only padded the string to the left the space after the \ can still be absent, so make that character optional
/3|6/>/36/

Check if the new row is valid

+1 Neat! you should include this online tester perl -M5.010 main.pl <<< 25, I've been getting some nice outputs!

Mind explaining a little bit how it works? I'm having too much fun generating them haha, I honestly didn't anticipate such good results.

Unfortunately, you need to add 3 bytes for -n, because the space and dash count too. The same rule is for command-line arguments. See "Special Invocations", second bullet-point: I count those as a difference in character count to the shortest equivalent invocation without them.

@EriktheGolfer No, +1 is OK because this program works fine from the commandline using -nE which is only 1 character more than -E.(see the article you referenced. This also gets rid of the need for -M5.010)  I always present my code as files because it is more convenient, but I always count options like this: If it can be run from the commandline I don't count the space and the dash. If it must be in a file (e.g. because it uses do$0) I do count the space and the dash

@TonHospel Oh, I didn't know you used -E. If so, you are good.

JavaScript (ES6), 154 bytes

f=(n,r=[],s=" ".repeat(n)+"/",t=s.replace(/ \/|\\ |\\$/g,_=>"  /  \\/\\".substr(Math.random()*8&6,2)))=>n?/^ +$|\\\//.test(t)?f(n,r,s):f(n-1,[...r,t],t):r
<input type="number" min=1 oninput=o.textContent=f(this.value).join`\n`><pre id=o>

I struggled with the implementation until I saw @TonHospel's answer, at which point it just degenerated into a port. Sample output:
         /\
        / /\
       /\   \
        /\   \
         /\  /
          / /\
         / / /\
            / /\
            \   \
             \

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

sort: votes


text:
Sum the unique numbers in a list
For this challenge, the objective is to take a list of integers, and output the sum of every unique integer in that list, i.e. count multiples of the same integer only once.
Your input will be a string in the format "{1,2,3,4}" with any amount of elements. The string will never have whitespace or be in a format that does not match the example above. A list with 0 elements should return 0.
Examples
"{1,2,3,4}" -> 10
"{5,2,5}" -> 7
"{13,13,13}" -> 13
"{-5,5,5}" -> 0
"{12,12,13,13,14,14}" -> 39
"{}" -> 0
"{3}" -> 3

This is code-golf, so the shortest answer in bytes wins.
Good luck!

In the future, please use the Sandbox to allow your challenges to get feedback before posting them on the main site.

Why the strict input format?

Since I dislike downvotes without comments, I'll explain why I downvoted, and hopefully provide some constructive criticism for your next challenge. 1) This challenge is very trivial in the vast majority of languages and 2) demanding that the input comes in a rigid string form makes it unnecessarily complicated for some languages that have do extra parsing for no good reason.

Jelly, 1 byte
S

TryItOnline
Since command line arguments are passed as a string to Python, it evaluates as a set*.
S then sums the resulting list Jelly will receive.
* except in the empty case (as pointed out by @Dennis) when "{}" evaluates to an empty dictionary, but this gets cast to a list of it's keys, which is an empty list.

Python 2, 21 18 bytes:
print sum(input())

Nice job muddyfish :)

Why would this work? sum([1,1,1])=3, not 1

The input format is python's default for a set. A set automatically removes duplicates

MATL, 4 bytes
Ugus

String delimiter in MATL is '.
Try it online!
Explanation
U    % Implicitly input string and evaluate it. Gives a cell array
g    % Convert to vector
u    % Unique
s    % Sum. Implicitly display

@JonathanAllan Whoops. It does now. Thanks!

Sounds like something a caveman might say haha! Ugus!Ugus!Ugus!

JavaScript (ES6), 61 bytes
s=>[...new Set(s.slice(1,-1).split`,`)].reduce((s,n)=>+n+s,0)

Without the unreasonable input format it's only 39 bytes:
f=a=>[...new Set(a)].reduce((s,n)=>s+n,0)

The ,0 is necessary to work with an empty array.

Doesn't work for me...

Actually, 2 bytes
≡Σ

Try it online!
≡ (eval) evaluates the input, which is thankfully specified in Python's set literal syntax. Σ then sums the set elements.

05AB1E, 9 bytes
0E¦¨',¡ÙO

Try it online!
Explanation
0          # push 0
 E         # push evaluated input
  ¦¨       # remove brackets
    ',¡    # split on ","
       Ù   # remove duplicates
        O  # sum

0E is needed as sum doesn't work on an empty list.

Gahhh... I didn't realize the challenge assumed the language would use { and } so I did Ù0¸˜O

@carusocomputing: Yeah, that input format isn't very good for 05AB1E. I started out with a list as well before I noticed the wording :/

Why doesn't sum work on an empty list?

@Cyoce: There seem to be a bug in the interpreter. Interestingly, sum do work on a list of empty lists.

Pyke, 9 4 bytes
F )s

Try it here!
Yes, I have to spend 3 bytes converting a set to a list because Pyke's sum function errors out on sets.
The space is required because the default behavior for a for-loop in Pyke is to print out the arguments

PHP, 34 Bytes
<?=array_sum(array_unique($argv));

Perl, 28 bytes
Includes +1 for -p
Give input on STDIN
#!/usr/bin/perl -p
s%-?\d*%$a{$&}//=$_+=$&%reg

Surprisingly hard to support the empty set and go below 29 bytes

Bash + coreutils, 38 bytes
bc<<<0$(tr ,}{ \\n|sort -u|paste -sd+)

Try it on ideone.com!
Explanation: using {1,2,1,4} as test case
        tr ,}{ \\n       # replace commas and braces with newlines (\n1\n2\n1\n4\n)
        |sort -u         # sort and print unique lines (\n1\n2\n4)
        |paste -sd+      # merge lines with '+' as delimiter (+1+2+4)
bc<<<0$(           )     # prepend '0' and calculate sum (7)

Note how prepending a '0' will also help to give a correct answer when the input list is empty ({}).
Run examples:
me@LCARS:/PPCG$ ./sum_unique.sh <<< "{}"
0
me@LCARS:/PPCG$ ./sum_unique.sh <<< "{3}"
3
me@LCARS:/PPCG$ ./sum_unique.sh <<< "{-5,5,5}"
0
me@LCARS:/PPCG$ ./sum_unique.sh <<< "{12,12,13,13,14,14}"
39

Octave, 29 bytes
@(x)sum(unique([eval(x){:}]))

This creates an anonymous function named ans can be called using ans('{1, 2, 3}').
Online demo
Explanation
The eval(x) converts the input string into a cell array of numbers. The [x{:}] converts the cell array of numbers into a normal array of numbers. Then we compute the unique elements and sum the result.

Ruby, 36 bytes
$><<eval(gets.scan(/-?\d+/).uniq*?+)

Search for all unique "integer-looking" strings in the input and join this list on the string +, then evaluate the resulting string and print the result.

BASH + CoreUtils + sed + bc 75 68 50 bytes
Saved a bunch thanks to Digital Trauma and seshoumara
sed '/{}/c0
s:[}{,]:\n:g'|sort -u|xargs|tr \  +|bc

tr , \\n, etc

@DigitalTrauma Thanks for the help. My BASH answers usually turn into a learning experience instead of a really well golfed answer.

You can merge sed and tr in one sed command and use xargs at the end, saving 13 bytes: sed 's:[}{]::g;y:,:\n:;/^$/c0'|sort -u|xargs|tr \  +|bc. There are two spaces before +. For a different way to shorten it further see my answer.

Mathematica, 8 9 bytes
Tr@*Union

Union deletes duplicates (and sorts), and Tr totals a list. A rare case when Mathematica can actually compete with golfing languages!

Tr@Union by itself is Tr[Union], which does not do anything. (e.g. f=Tr@Union; f[{1,2,1}]) You may want Tr@*Union.

I see your point and you're probably right. But just to clarify for me: Tr@Union[{1,2,1}] does work correctly, while f=Tr@Union; f[{1,2,1}] does not. Why does that imply (according to community standards) that Tr@Union isn't acceptable?

@GregMartin By meta consensus, any unnamed functions must be able to be captured into a name; by that logic, f=(Tr@Union); f[{1,2,1}] would have to be valid.

Excellent link. Thank you for taking the time to teach me! :)

Zsh, 41 34 bytes
<<<$[${${(us:,:)${1/\{}/\}}// /+}]

Try it online!
Try it online!
${  / / } is replacement, ${  // / } is global replacement, (s:,:) splits the string on commas, (u) keeps the unique elements.

Groovy (81 Bytes)
z={x->Eval.me(x.replaceAll("\\{","\\[").replaceAll("\\}","\\]")).unique().sum()}

Try it online:
https://groovyconsole.appspot.com/edit/5074458091978752
28 Bytes if you Use [] as brackets...
z={Eval.me(it).unique().sum()}

R, 51 bytes
s=scan;sum(unique(s(t=gsub("\\{|}|,"," ",s(,"")))))

Bash + GNU utilities, 54
eval printf '0%s\\n' $1|tr -d {}|sort -u|paste -sd+|bc

Input is given as a command-line parameter.  Note that the input must be quoted to prevent expansion by the calling shell (this would be handy, and save some bytes, but I feel like that would be cheating a bit).
The input format is mostly a bash brace expansion, but it doesn't expand as we want it to for a 0 or 1 element list, so a bit more preprocessing is required before piping to sort -u.
Ideone.

Pyth, 3 bytes
Unfortunately, the sum builtin doesn't work in Pyth with sets.  I have to convert to a list first...
s[F

Explanation:
 [   Construct list
  F  By splatting in the elements of the input
s    Sum up

Taking input as a list-type form would actually be a byte shorter:
s{

Which is the sum of the {de-duplicated input.

Perl 6, 29 bytes
*.comb(/<[-\d]>+/).unique.sum

Example:
# give the Whatever lambda a name for clarity
my &code = *.comb(/<[-\d]>+/).unique.sum;

say code '{1,2,3,4}'; # 10
say code '{5,-5,5}';  # 0
say code '{}';        # 0

C#, 103 bytes
(i)=>i[1]=='}'?0:Regex.Match(i,"{(.*)}").Groups[1].Value.Split(',').Select(int.Parse).Distinct().Sum();

this challange its pretty pointless really

ListSharp, 134 bytes
STRG s=INPUT[""] AS STRG
SHOW=ROWSPLIT STRG["0"+GETRANGE s FROM [2] TO [s LENGTH-1]] BY [","]<c#.Select(int.Parse).Distinct().Sum()c#>

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Print a specific value in the Wythoff matrix modulo 2
The Wythoff matrix is an infinite matrix consisting of the Grundy numbers of each square on a chessboard in Wythoff's game.
Each entry in this matrix is equal to the smallest nonnegative number that does not appear anywhere above, to the left, or diagonally northwest of the position of the entry.
The top-left 20-by-20 square looks like this:
  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19
  1  2  0  4  5  3  7  8  6 10 11  9 13 14 12 16 17 15 19 20
  2  0  1  5  3  4  8  6  7 11  9 10 14 12 13 17 15 16 20 18
  3  4  5  6  2  0  1  9 10 12  8  7 15 11 16 18 14 13 21 17
  4  5  3  2  7  6  9  0  1  8 13 12 11 16 15 10 19 18 17 14
  5  3  4  0  6  8 10  1  2  7 12 14  9 15 17 13 18 11 16 21
  6  7  8  1  9 10  3  4  5 13  0  2 16 17 18 12 20 14 15 11
  7  8  6  9  0  1  4  5  3 14 15 13 17  2 10 19 21 12 22 16
  8  6  7 10  1  2  5  3  4 15 16 17 18  0  9 14 12 19 23 24
  9 10 11 12  8  7 13 14 15 16 17  6 19  5  1  0  2  3  4 22
 10 11  9  8 13 12  0 15 16 17 14 18  7  6  2  3  1  4  5 23
 11  9 10  7 12 14  2 13 17  6 18 15  8 19 20 21  4  5  0  1
 12 13 14 15 11  9 16 17 18 19  7  8 10 20 21 22  6 23  3  5
 13 14 12 11 16 15 17  2  0  5  6 19 20  9  7  8 10 22 24  4
 14 12 13 16 15 17 18 10  9  1  2 20 21  7 11 23 22  8 25 26
 15 16 17 18 10 13 12 19 14  0  3 21 22  8 23 20  9 24  7 27
 16 17 15 14 19 18 20 21 12  2  1  4  6 10 22  9 13 25 11 28
 17 15 16 13 18 11 14 12 19  3  4  5 23 22  8 24 25 21 26 10
 18 19 20 21 17 16 15 22 23  4  5  0  3 24 25  7 11 26 12 13
 19 20 18 17 14 21 11 16 24 22 23  1  5  4 26 27 28 10 13 25

There is currently no known efficient algorithm for computing an arbitrary entry in the Wythoff matrix. However, your task in this problem is to try to design a heuristic function that will tell whether the number at a specific coordinate wythoff(x, y) is even or odd.
Your program may not contain more than 64 KB (65,536 bytes) of source code, or use more than 2 MB (2,097,152 bytes) of working memory.
In particular for memory usage, this means that the maximum resident set size of your program may not exceed 2 MB more than the maximum resident set size of an empty program in that language. In the case of an interpreted language, it would be the memory usage of the interpreter / virtual machine itself, and in the case of a compiled language, it would be the memory usage of a program that executes the main method and does nothing.
Your program will be tested on the 10000 x 10000 matrix for row values in 20000 <= x <= 29999 and column values in 20000 <= y <= 29999.
The score of your program is the accuracy rate (number of correct guesses) your program achieves, with shorter code acting as a tiebreaker.

01.R is a 05AB1E that outputs true or false randomly. Let 0 be true and 1 be false, my program will theoretically be correct ~50% of the time. Is this a valid entry?

@carusocomputing Actually, I forgot to mention that randomized solutions are not allowed — your program should produce the same output for the same input every time, although I suspect that the word function implies that.

If I fix the seed of my prng on each call, it will produce the same output for identical input, and I know what you mean but you will probably have to word it more specifically somehow.

I get something very different when I search for Wythoff Matrix

@Linus Would "Wythoff's Game Matrix" be better? I saw that page too.

@miles Pseudorandom solutions are fine, just not ones that use R like the 05AB1E solution, which are not guaranteed to return the same value every time.

@Vlo For each row, the residuals are eventually periodic, which makes me think that there are at least some heuristics that would work.

Let us continue this discussion in chat.

Python; accuracy = 54,074,818; size = 65,526 bytes
Previous scores: 50,227,165; 50,803,687; 50,953,001
#coding=utf-8
d=r'''<65,400 byte string>'''
def f(x,y):
 a=max(x,y)-20000;b=min(x,y)-20000;c=(a*(a+1)//2+b)%523200
 return(ord(d[c//8])>>(c%8))&1

This approach divides all unique entries of the matrix into 523,200 groups and reads the best guess for the group (x, y) from a binary string. You can download the full source code from Google Drive.
I've used @PeterTaylor's parities to generate the string and to compute the accuracy.

I tried many different, more interesting approaches, but in the end, a simple hardcode outscored all of them...

Hardcoding is also a valid approach — it might turn into, say, which hardcoding scheme returns the best result.

Not saying otherwise, but since the distribution of the parities is very obviously non-random, I was hoping to outscore this approach. So far, all my attempts have failed though.

Nah, it's fine. It just means that this problem is too hard to do properly. I've been making a bunch more problems of this style except one-dimensional. They're all in the sandbox if you want to check them out.

CJam (accuracy 50016828/100000000, 6 bytes)
{+1&!}

(In ALGOL-style pseudocode for non-CJammers: return ((x + y) & 1) == 0).
This performs better than any of the other two dozen simple heuristics I've tried. It's even better than any combination with the next two best ones.

The score assumes that my calculated section of the matrix is correct. Independent verification welcomed. I'm hosting the calculated parity bits at http://cheddarmonk.org/codegolf/PPCG95604-parity.bz2 (8MB download, extracts to 50MB text file: since the matrix is symmetric about the main diagonal, I've only included each line starting from the main diagonal, so you have to offset, transpose, and bitwise OR to get the full square).
The code which I used to calculate it is Java. It uses the definition fairly straightforwardly, but with a set data structure which run-length encodes the ranges so that it's quick to skip to the next permitted value. Further optimisation would be possible, but it runs on my moderately old desktop in about two hours and 1.5GB of heap space.
import java.util.*;

public class PPCG95604Analysis
{
    static final int N = 30000;

    public static void main(String[] args) {
        Indicator[] cols = new Indicator[N];
        Indicator[] diag = new Indicator[N];
        for (int i = 0; i < N; i++) {
            cols[i] = new Indicator();
            diag[i] = new Indicator();
        }

        int maxVal = 0;

        for (int y = 0; y < N; y++) {
            Indicator row = new Indicator(cols[y]);

            for (int x = y; x < N; x++) {
                Indicator col = cols[x];
                Indicator dia = diag[x - y];

                Indicator.Result rr = row.firstCandidate();
                Indicator.Result rc = col.firstCandidate();
                Indicator.Result rd = dia.firstCandidate();

                while (true) {
                    int max = Math.max(Math.max(rr.candidateValue(), rc.candidateValue()), rd.candidateValue());
                    if (rr.candidateValue() == max && rc.candidateValue() == max && rd.candidateValue() == max) break;

                    if (rr.candidateValue() != max) rr = rr.firstCandidateGreaterThan(max - 1);
                    if (rc.candidateValue() != max) rc = rc.firstCandidateGreaterThan(max - 1);
                    if (rd.candidateValue() != max) rd = rd.firstCandidateGreaterThan(max - 1);
                }

                if (y >= 20000 && x >= 20000) System.out.format("%d", rr.candidateValue() & 1);
                maxVal = Math.max(maxVal, rr.candidateValue());
                rr.markUsed();
                rc.markUsed();
                rd.markUsed();
            }
            if (y >= 20000) System.out.println();
        }
    }

    static class Indicator
    {
        private final int INFINITY = (short)0xffff;
        private final int MEMBOUND = 10000;

        private short[] runLengths = new short[MEMBOUND];

        public Indicator() { runLengths[1] = INFINITY; }

        public Indicator(Indicator clone) { System.arraycopy(clone.runLengths, 0, runLengths, 0, MEMBOUND); }

        public Result firstCandidate() {
            // We have a run of used values, followed by a run of unused ones.
            return new Result(1, 0xffff & runLengths[0], 0xffff & runLengths[0]);
        }

        class Result
        {
            private final int runIdx;
            private final int runStart;
            private final int candidateValue;

            Result(int runIdx, int runStart, int candidateValue) {
                this.runIdx = runIdx;
                this.runStart = runStart;
                this.candidateValue = candidateValue;
            }

            public int candidateValue() {
                return candidateValue;
            }

            public Result firstCandidateGreaterThan(int x) {
                if (x < candidateValue) throw new IndexOutOfBoundsException();

                int idx = runIdx;
                int start = runStart;
                while (true) {
                    int end = start + (0xffff & runLengths[idx]) - 1;
                    if (end > x) return new Result(idx, start, x + 1);

                    // Run of excluded
                    start += 0xffff & runLengths[idx];
                    idx++;
                    // Run of included
                    start += 0xffff & runLengths[idx];
                    idx++;

                    if (start > x) return new Result(idx, start, start);
                }
            }

            public void markUsed() {
                if (candidateValue == runStart) {
                    // Transfer one from the start of the run to the previous run
                    runLengths[runIdx - 1]++;
                    if (runLengths[runIdx] != INFINITY) runLengths[runIdx]--;
                    // May need to merge runs
                    if (runLengths[runIdx] == 0) {
                        runLengths[runIdx - 1] += runLengths[runIdx + 1];
                        for (int idx = runIdx; idx < MEMBOUND - 2; idx++) {
                            runLengths[idx] = runLengths[idx + 2];
                            if (runLengths[idx] == INFINITY) break;
                        }
                    }

                    return;
                }

                if (candidateValue == runStart + (0xffff & runLengths[runIdx]) - 1) {
                    // Transfer one from the end of the run to the following run.
                    if (runLengths[runIdx + 1] != INFINITY) runLengths[runIdx + 1]++;
                    if (runLengths[runIdx] != INFINITY) runLengths[runIdx]--;
                    // We never need to merge runs, because if we did we'd have hit the previous case instead
                    return;
                }

                // Need to split the run. From
                //   runIdx: a+1+b
                // to
                //   runIdx: a
                //   runIdx+1: 1
                //   runIdx+2: b
                //   runIdx+3: previous val at runIdx+1
                for (int idx = MEMBOUND - 1; idx > runIdx + 2; idx--) {
                    runLengths[idx] = runLengths[idx - 2];
                }
                runLengths[runIdx + 2] = runLengths[runIdx] == INFINITY ? INFINITY : (short)((0xffff & runLengths[runIdx]) + runStart - 1 - candidateValue);
                runLengths[runIdx + 1] = 1;
                runLengths[runIdx] = (short)(candidateValue - runStart);
            }
        }
    }
}

J, accuracy = 50022668/108 = 50.0227%, 4 bytes
2|*.

Takes the coordinates as two arguments, computes the LCM between them and takes it modulo 2. A 0 means it is even and a 1 means it is odd.
The performance is based on the parity bits provided by @Peter Taylor.
The PRNG version before for 7 bytes, 2|?.@#. had an accuracy of 50010491/108.
Explanation
2|*.  Input: x on LHS, y on RHS
  *.  LCM(x, y)
2|    Modulo 2

The parity of the LCM is the parity of the bitwise AND. Does that save you a byte? The fascinating thing is that it's so obviously a bad heuristic (it gives 1 a mere 25% of the time, when the correct proportion is almost exactly 50%), and yet it does better than many which aren't so obviously bad.

Thanks, but unfortunately bitwise AND in J is literally AND.

@PeterTaylor That sort of surprising heuristic discovery is what challenges like this one are supposed to be all about.


text:
String Similarity using Jaro-Winkler
String Similarity
String similarity is basically a ratio of how similar one string is to another. This can be calculated in many ways, and there are various algorithms out there for implementing a ratio calculation for string similarity, some being more accurate than others. It's actually very useful to use these methods in diff algorithms for the calculation of how similar one document or string is to one another.
A couple of the most popular algorithms are:

The Levenshtein Distance Algorithm
Jaro-Winkler Distance Algorithm
Adjacent Pairing Algorithm

In practice, calculating all three and taking the average works very well for most purposes. However, to keep the challenge more simple, I am not going to over-ask. For the purpose of this challenge, you must implement the Jaro-Winkler algorithm.
Rules

Built ins are welcome, but must be marked non-competing, (E.G. .L - 05AB1E)
Your input must only be 2 strings f(a,b).
The comparison should be Case insensitive, that is to say:  f('aBc','aBC')=f('abc','Abc')=f('abc','abc')=1.0
In other words, convert the strings to lower case before the comparison or something like that.
Your output must be a double, float or ratio appropriately expressed in the language of your choice; as long as the output is obviously interpreted, it's fine.
This is code-golf, shortest answer wins.

Examples

jw(a,b) represents Jaro-Winkler similarity.

Example Algorithm in Java
/**
 * Calculates the similarity score of objects, where 0.0 implies absolutely
 * no similarity and 1.0 implies absolute similarity.
 *
 * @param first
 *            The first string to compare.
 * @param second
 *            The second string to compare.
 * @return A number between 0.0 and 1.0.
 */
public static final double jaroSimilarity(final String first,
        final String second) {
    final String shorter;
    final String longer;

    // Determine which String is longer.
    if (first.length() > second.length()) {
        longer = first.toLowerCase();
        shorter = second.toLowerCase();
    } else {
        longer = second.toLowerCase();
        shorter = first.toLowerCase();
    }

    // Calculate the half length() distance of the shorter String.
    final int halflength = (shorter.length() / 2) + 1;

    // Find the set of matching characters between the shorter and longer
    // strings. Note that
    // the set of matching characters may be different depending on the
    // order of the strings.
    final String m1 = getSetOfMatchingCharacterWithin(shorter, longer,
            halflength);
    final String m2 = getSetOfMatchingCharacterWithin(longer, shorter,
            halflength);

    // If one or both of the sets of common characters is empty, then
    // there is no similarity between the two strings.
    if (m1.length() == 0 || m2.length() == 0)
        return 0.0;

    // If the set of common characters is not the same size, then
    // there is no similarity between the two strings, either.
    if (m1.length() != m2.length())
        return 0.0;

    // Calculate the number of transpositions between the two sets
    // of common characters.
    final int transpositions = transpositions(m1, m2);

    // Calculate the distance.
    final double dist = (m1.length() / ((double) shorter.length())
            + m2.length() / ((double) longer.length()) + (m1.length() - transpositions)
            / ((double) m1.length())) / 3.0;
    return dist;

}

/**
 * Gets a set of matching characters between two strings. Two characters
 * from the first string and the second string are considered matching if
 * the character's respective positions are no farther than the limit value.
 *
 * @param first
 *            The first string.
 * @param second
 *            The second string.
 * @param limit
 *            The maximum distance to consider.
 * @return A string contain the set of common characters.
 */
private static final String getSetOfMatchingCharacterWithin(
        final String first, final String second, final int limit) {

    final StringBuilder common = new StringBuilder();
    final StringBuilder copy = new StringBuilder(second);
    for (int i = 0; i < first.length(); i++) {
        final char ch = first.charAt(i);
        boolean found = false;

        // See if the character is within the limit positions away from the
        // original position of that character.
        for (int j = Math.max(0, i - limit); !found
                && j < Math.min(i + limit, second.length()); j++) {
            if (copy.charAt(j) == ch) {
                found = true;
                common.append(ch);
                copy.setCharAt(j, '*');
            }
        }
    }
    return common.toString();
}

/**
 * Calculates the number of transpositions between two strings.
 *
 * @param first
 *            The first string.
 * @param second
 *            The second string.
 * @return The number of transpositions between the two strings.
 */
private static final int transpositions(final String first,
        final String second) {
    int transpositions = 0;
    for (int i = 0; i < first.length(); i++) {
        if (first.charAt(i) != second.charAt(i)) {
            transpositions++;
        }
    }
    transpositions /= 2;
    return transpositions;
}

Here's all my test cases, if you want another one, ask me.
jw ('abc','AbC')=1.0
jw ('i walked to the store','the store walked to i')=0.7553688141923436
jw ('seers','sears')=0.8666666666666667
jw ('banana','bandana')=0.9523809523809524
jw ('abc','xyz')=0.0
jw ('1234567890qwertyuiopasdfghjklzxcvbnm','mnbvcxzlkjhgfdsapoiuytrewq0987654321')=0.5272904483430799
jw ('#faceroll:j4565j6eekty;fyuolkidsujkr79tp[8yiusyweryhjrn7ktgm9k,u[pk7jf6trhvgag5vhbdtnfymghu,','#faceroll:ezbrytnmugof7ihdgsyftwacvegybrnftiygihdugs5ya4tsyrdu6htifj7yif')=0.6512358338650381

Related

You should specify the actual algorithm to be used in the challenge instead of linking to external resources. Challenges should be self-contained.

^ (links tend to die over time)

Wikipedia links? Fair enough though. Snippet posted.

@Emigna that's exactly the difference, they split on \\s and didn't count letter space pairings. This algorithm is pretty useful in written language because it compares by word, and ignores whitespace as well.

The article in the link is pretty messy and the similarity-algorithm described was only for characters. The java implementation further down mentioned whitespace though. Easy enough to ignore whitespace though.

I'll clarify more on the other question to include that stipulation.

Isn't getSetOfMatchingCharacterWithin off by 1 on the upper limit ? I think it should be j <= Math.min(i + limit, second.length()-1)

Python 3, 351 350 347 346 bytes
l=len
r=range
a,b=input(),input()
x,y=(a.lower(),b.lower())[::1-2*(l(a)>l(b))]
h=l(y)//2+1
n=o=''
for a,b in(x,y),(y,x):
 for i in r(l(a)):
  for j in r(max(0,i-h),min(i+h,l(b))):
   if b[j]==a[i]:o+=a[i];b=b[:j]+'*'+b[j+1:];break
 n,o=o,n
q,z=l(n),l(o)
print(0if(any((n,o))-1or z!=q)else(z/l(y)+q/l(x)+(z-sum(n[i]!=o[i]for i in r(l(n)))/2)/z)/3)

Expects the two inputs on STDIN, newline-separated. Example run:
$ echo -e "seers\nsears" | python jaro.py
0.8666666666666667

Saved 1 byte thanks to @Shebang!

I know we're a way past when you posted this, but you can save 2 bytes by making the indent levels for the inner for group as SPACE TAB TAB+SPACE SPACE (I hope this makes sense). Also, you can do (a.lower(),b.lower())[::1+-2*(l(a)>l(b))] -> (b.lower(),a.lower())[::2*(l(a)>l(b))-1] to save another byte.

@Shebang Your first trick only works in Python 2, so I can't use it. Thanks for the other one, though!

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Print this tic-tac-toe board!
Here is a tic-tac-toe board:
   a     b     c
      |     |
1  -  |  -  |  -
 _____|_____|_____
      |     |
2  -  |  -  |  -
 _____|_____|_____
      |     |
3  -  |  -  |  -
      |     |

Given a set of moves, print the board with the tokens on.
Input will be taken in as moves separated by spaces, with each move being:

First, the token that's going
Next, the letter of the column it is moving on
Last, the number of the row it is moving on

Note that normal tic-tac-toe rules don't matter.
Also, there is no need to print the letters and numbers.
For example, the input Ob2 Xc2 Ob3 Xa1 would result in
     |     |
  X  |  -  |  -
_____|_____|_____
     |     |
  -  |  O  |  X
_____|_____|_____
     |     |
  -  |  O  |  -
     |     |

Remember, this is code-golf, so the code with the smallest number of bytes wins.
Leaderboards
Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.
To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:
# Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:
# Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:
# Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the leaderboard snippet:
# [><>](http://esolangs.org/wiki/Fish), 121 bytes

var QUESTION_ID=95629,OVERRIDE_USER=12537;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="
"+e.body.replace(OVERRIDE_REG,"")+"
")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
 <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b">

Leaderboard

	Author	Language	Size

Winners by Language

Language	User	Score

{{PLACE}}	{{NAME}}	{{LANGUAGE}}	{{SIZE}}	Link

{{LANGUAGE}}	{{NAME}}	{{SIZE}}	Link

A thing to avoid with writing challenges is Cumbersome I/O formats. Please make your input format flexible enough. Next time try the Sandbox.

@EriktheGolfer cumbersome? This input format is plain and obvious

@edc65 I meant that, I want to get input in any format, not just this one, but I guess it's late by now. I think you mean it's visually clear, but I couldn't handle it at all. Why spaces and not some other separator for example?

@EriktheGolfer don't take me wrong, but if your super extra esoteric language cannot handle blank spaces, too bad ... you'll have to use something else just this time.

@edc65 For example, in Sesos it would be pretty difficult to even load the input data. I would prefer a list of integers (three ints for one move), like 1 2  3 for Xb3 (doesn't have to be exactly that).

I think it should remain there for at least 2 days, or until you think you've got enough feedback, and are ready to post it. Impatience might result in downvotes (I haven't downvoted, by the way).

Does the output need to be a string, or can it be formatted using a built-in, like this or this? (the I/O formatting makes my code 2x longer...)

@JHM It just needs to be in the format it is in the question.

JavaScript (ES6), 136 133 129 bytes

let f =

i=>eval("for(y=9,s='';y--;s+=`\n`)for(x=18;--x;)s+=x%6-3|y%3-1?' __|'[x%6?y/3:3]||' ':i[i.search('cba'[x/6|0]+(10-y)/3)-1]||'-'")

console.log(f("Ob2 Xc2 Ob3 Xa1"))

Python (2.7), 188 180 bytes
def f(s):a,b=3*[' '*5],3*['_'*5];c,d,e=[['  '+dict((m[1:],m[0])for m in s.split(' ')).get(x+y,'-')+'  'for x in'abc']for y in'123'];print'\n'.join(map('|'.join,[a,c,b,a,d,b,a,e,a]))

In the third line you can remove the spaces before the 's

Welcome to python golfing! Take a look at the Python golf tips. You can separate statements with ; allowing you to put all your code on one line to save on indentation.

for y in '123' -> for y in'123'. Also, what xnor said: you can make your function a one-liner, using ; to separate statements. Using all of these golfing tips, you can golf 6 bytes.

Python 2, 112 bytes
s=input()+'- '
r=3;exec"print'|'.join([' '*5,'  %s  '%s[s.find(c+`r/3`)-1],'_'*5][r%11%3]for c in'abc');r+=1;"*9

Nine rows are printed corresponding to row indices r. The row index is counted up from 3 to 11 in an exec loop. Each row consists of vertical lines | joining three 5-character segments that cycle between:

Five spaces
Two spaces, a player symbol, then two spaces
Five underscores

The type is made to cycle with r%3, except the last row has spaces rather than underscores, achieved with r%11%3.
To find the player symbol for the current cell, we look at the row number  r/3 and the column letter c from "abc". We concatenate them to make a two-character string like b3, find the index of it in the input string, and then take the symbol (X or O) one index earlier. If neither player played there, the find will default to -1, which decrements to -2. We hack s[-2] to be - by appending two characters when we take input.

Batch, 341 339 305 287 bytes
@for %%a in (a1 a2 a3 b1 b2 b3 c1 c2 c3)do @set %%a=-
@for %%a in (%*)do @set s=%%a&call call set %%s:~1%%=%%s:~0,1%%
@set s="     |     |     "
@for %%l in (%s% "  %a1%  |  %b1%  |  %c1%" %s: =_% %s% "  %a2%  |  %b2%  |  %c2%" %s: =_% %s% "  %a3%  |  %b3%  |  %c3%" %s%)do @echo %%~l

Assumes consistent output. Edit: Saved 2 bytes by removing unnecessary spaces. Saved 34 bytes by writing the output using a for loop. Saved 18 bytes by eliminating the subroutine.

Java, 138 bytes
Edit:

-2 bytes off. Thanks to @Kevin Kruijssen

Snipet:
m->{char[][]o=new char[3][3];for(char[]a:m)o[a[1]-'a'][a[2]-'0']=a[0];for(char[]a:o)System.out.println(a[0]+'|'+a[1]+'|'+a[2]+"\n-----");}

Code:
public static void tictactoe(char[][]moves){
  char[][]o=new char[3][3];
  for(char[]a:moves){
    o[a[1]-79][a[2]-48]=a[0];
  }
  for(char[]a:o){
    System.out.println(a[0]+'|'+a[1]+'|'+a[2]+"\n-----");
  }
}

o[a[1]-'a'][a[2]-'0']=a[0] can be golfed by two bytes to o[a[1]-97][a[2]-48]=a[0]

but if's the wrong output, isn't it?

Which mistake do you mean?

The output format is not the same as asked by the OP.

PHP, 187 Bytes
<?for(;$i++<162;)$s.=$i%18?($i%6?($i<144&&$i%54>36?"_":($i<144&&$i%54>18&&$i%6==3?"-":" ")):"|"):"\n";foreach(explode(" ",$_GET[a])as$t)$s[20+6*(1+($t[1]<=>b))+54*($t[2]-1)]=$t[0];echo$s;

Takes the input as string. If I could use an array it can be reduce to $_GET[a] instead of explode(" ",$_GET[a])
207 Bytes
<?foreach(explode(" ",$_GET[a])as$t)$a[(1+($t[1]<=>b))+3*($t[2]-1)]=$t[0];for(;$i++<162;)$s.=$i%18?($i%6?($i<144&&$i%54>36?"_":" "):"|"):"\n";for(;$x<9;)$s[18+54*(($x/3)^0)+2+6*($x%3)]=$a[+$x++]??"-";echo$s;

The simplest idea to create this 194 Bytes
<?for(;++$i<10;)$s.=($i==9||$i%3?($i%3==2?"  -  |  -  |  -  ":"     |     |     "):"_____|_____|_____")."\n";foreach(explode(" ",$_GET[a])as$t)$s[20+6*(1+($t[1]<=>b))+54*($t[2]-1)]=$t[0];echo$s;

Mathematica, 205 bytes
StringReplacePart[a="     |     |
";b="  -  |  -  |  -
";c="_____|_____|_____
";{a,b,c,a,b,c,a,b,a}<>"",##]&@@Transpose[{#,{#,#}&[54LetterNumber@#2+6FromDigits@#3-39]}&@@@Characters/@StringSplit@#]&

This would be way shorter if I could use the built-in... (92 bytes)
Grid@SparseArray[{LetterNumber@#2,FromDigits@#3}->#&@@@Characters/@StringSplit@#,{3,3},"-"]&

Autovim,  110 bytes (not competing)
Test driving Autovim... This is pretty much a Vimscript answer. Not competing because Autovim is still being developed.
ñ5i ␛a|␛ÿp3hr-phv0r_⌥v$kkyPPy2jPP$⌥vG$xGđkÿjp
…nsplit(@m)
ñğ0(@n[2]*3-2)j((char2nr(@n[1])-96)*6-4)lr(@n[0])
e…

To run it:
./bin/autovim run tictactoe.autovim -ni -@m "Ob2 Xc2 Ob3 Xa1"

Ungolfed:
execute "normal 5i \<esc>a|\<esc>yyp3hr-phv0r_\<c-v>$kkyPPy2jPP$\<c-v>G$xGddkyyjp"
for @n in split(@m)
execute "normal gg0".(@n[2]*3-2)."j".((char2nr(@n[1])-96)*6-4)."lr".(@n[0]).""
endfor

Explanation to follow if there is interest :)

Groovy, 174 Bytes
{s->def r=0,o,t=[:];s.split(' ').each{t[it[1..2]]=it[0]};9.times{y->o='';17.times{x->o+=x%6==5?'|':y in [2,5]?'_':x%6==2&&y%3==1?t['abc'[r++%3]+(y+2)/3]?:'-':' '};println o}}

ungolfed:
{s->
    def r=0, o, t=[:];
    s.split(' ').each{
        t[it[1..2]]=it[0]
    };
    9.times{y->
        o='';
        17.times{x->
            o+= x%6==5 ? '|' : y in [2,5]? '_' : x%6==2 && y%3==1 ? t['abc'[r++%3]+(y+2)/3]?:'-' : ' '
        };
        println o
    }
}

CJam, 62 bytes
" -_ -_ - "_'-Ser_+_@\]3*sqS/{)~\)'a-F*@+3*G+\t}/9/5/'|9*a*zN*

Try it online
Explanation:
" -_ -_ - "_'-Ser_+_@\]3*s e# Build a 135 character string representing the
                           e# columns of the board (top to bottom, left to right)
qS/{)~\)'a-F*@+3*G+\t}/    e# Process the input, put the tokens (O,X) in the string
                           e# The tokens have to placed at indexes
                           e# [19 22 25 64 67 70 109 112 115]
                           e# This is done with the formula 3*(15x+y)+16,
                           e# where x is the code point of the column letter
                           e# (minus 'a') and y is the row number.
9/5/'|9*a*zN*              e# Split into its parts, add the column separators, zip
                           e# and join with newlines.


text:
A sign showing grouped opening hours of a cafe
You have probably seen these signs on the doors of various shops:

OPENING HOURS
mon-fri 0900-1800
  sat-sun 1100-1530

The task here is to generate a sign like that, grouping consecutive days with the same opening hours, from a list of opening hours for the whole week. Note that the week "wraps around" for what is considered consecutive.
Input:

7 elements, representing the opening hours for each day in a week, starting with Monday.
Each element is a string, on the form XXXX-XXXX
Example input:
0900-1800 0900-1800 0930-1730 0930-1730 0900-1500 1100-1500 1100-1500

It's ok to send the input as an array (for instance as input to a function if you don't read from stdin)

Output:

A list of opening hours, where consecutive days with the same opening hours are shown as a range. Note that sunday (the last day) and monday (the first day) also are consecutive days.
A day where the day doesn't have similar opening hours to the days before or after is printed by itself
Days are specified as three lowercase letters: mon tue wed thu fri sat sun
Remember that first element in the input corresponds to mon, next to tue etc.
Opening hours are shown as in the input
Two examples
mon-fri 0900-1800, sat-sun 1100-1500
mon-wed 1030-1530, thu 100-1800, fri-sun 1200-1630

The output should be sorted, so ranges appear in the order the days do in the week. Monday is preferred to be first, but it may happen it is not first in a group because the week wraps. So in this case tue is the first range.
tue-fri 0900-1800, sat-mon 1100-1500

Don't group unless consecutive, here wednesday and friday have same opening hours but are separated by a Thursday with different opening hours so they are listed by themselves.
mon-tue 1000-1200, wed 0900-1500, thu 1000-1800, fri 0900-1500, sat-sun 1000-1500

The output can be either comma-separated as the examples here, or separated by a newline as in the example on top.

Test cases
First line is input, second line is expected output
0900-1800 0900-1800 0900-1800 0900-1800 0900-1800 1100-1500 1100-1500
mon-fri 0900-1800, sat-sun 1100-1500

0900-1800 0900-1800 0900-1800 0930-1700 0900-1800 1100-1500 1100-1500
mon-wed 0900-1800, thu 0930-1700, fri 0900-1800, sat-sun 1100-1500

1100-1500 0900-1800 0900-1800 0900-1800 0900-1800 1100-1500 1100-1500
tue-fri 0900-1800, sat-mon 1100-1500

1100-1500 1100-1500 0900-1800 0900-1800 0900-1800 0900-1800 1100-1500
wed-sat 0900-1800, sun-tue 1100-1500

1200-1500 1100-1500 0900-1800 0900-1800 0900-1800 0900-1800 1100-1500
mon 1200-1500, tue 1100-1500, wed-sat 0900-1800, sun 1100-1500

Rules
This is code-golf, so the shortest answer in bytes wins.

Welcome to Programming Puzzles and Code Golf. This is a good challenge; well done! In future, I would recommend using the sandbox before posting a challenge. (You know, just in case...)

Having Sunday and Monday as consecutive seems odd to me...

I feel like there should be a test-case for "mon-sun" just in case any submission doesn't properly handle that particular base case.

JavaScript (ES6), 182 173 170 163 157 bytes
Saved 6 bytes with the help of edc65
Takes input as an array of strings and directly prints the result to the console:
h=>{for(D="montuewedthufrisatsun".match(/.../g),d=c=i=j=0;j<8;y=d)h[i]==h[6]?i++:(v=h[d=(i+j++)%7])!=c&&(j>1&&console.log(D[x]+(x-y?'-'+D[y]:''),c),x=d,c=v)}

Formatted and commented
h => {                               // input = list h of opening hours
  for(                               //
    D = "montuewedthufrisatsun"      // D = list of abbreviated names of days
        .match(/.../g),              //
    d =                              // d = current day of week
    c =                              // c = current opening hours
    i =                              // i = first day of week to process
    j = 0;                           // j = day counter
    j < 8;                           // stop when 7 days have been processed
    y = d                            // update y = last day of current day range
  )                                  //
  h[i] == h[6] ?                     // while the opening hours of day #i equal the opening
    i++                              // hours of sunday: increment i
  : (v = h[d = (i + j++) % 7]) != c  // else, if the new opening hours (v) of the current
    && (                             // day (d) doesn't match the current opening hours (c):
      j > 1 &&                       //   if this is not the first iteration:
        console.log(                 //     print:
          D[x] +                     //     - the first day of the current day range (x)
          (x - y ?                   //     - followed by either an empty string
            '-' + D[y]               //       or a '-' and the last day of the range
          : ''),                     //       (if they differ)
          c                          //     - the corresponding opening hours
        ),                           //   (endif)
      x = d,                         //   update x = first day of current day range
      c = v                          //   update c = current opening hours
    )                                // (endif)
}                                    // (end)

Test cases

let f =

h=>{for(D="montuewedthufrisatsun".match(/.../g),d=c=i=j=0;j<8;y=d)h[i]==h[6]?i++:(v=h[d=(i+j++)%7])!=c&&(j>1&&console.log(D[x]+(x-y?'-'+D[y]:''),c),x=d,c=v)}

f(["0900-1800", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500", "1100-1500"]);
console.log('-');
f(["0900-1800", "0900-1800", "0900-1800", "0930-1700", "0900-1800", "1100-1500", "1100-1500"]);
console.log('-');
f(["1100-1500", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500", "1100-1500"]);
console.log('-');
f(["1100-1500", "1100-1500", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500"]);
console.log('-');
f(["1200-1500", "1100-1500", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500"]);

D='montuewedthufrisatsun'.match(/.../g) using D as an array instead of a function should save some byte

@edc65 - Unfortunately D() can be called with -1 (when we look for 'the day before Monday'), which works with substr() but would not work with an array.

@edc65 - EDIT: by combining your method with another fix, this is definitely a win. Thanks!

Batch, 334 bytes
@echo off
set/af=l=w=0
set h=%7
call:l mon %1
call:l tue %2
call:l wed %3
call:l thu %4
call:l fri %5
call:l sat %6
call:l sun %7
if not %w%==0 set l=%w%
if %f%==0 set f=mon
call:l 0 0
exit/b
:l
if not %h%==%2 (
if %f%==0 (set w=%l%)else if %f%==%l% (echo %f% %h%)else echo %f%-%l% %h%
set f=%1
set h=%2
)
set l=%1

Takes input as command-line parameters, outputs each group on a separate line. Works by comparing each day's hours to the previous day, tracking f as the first day in the group, h as the hours for that group, l as the last day in the group and w for when the last group wraps back to the start of the week. When a mismatch is found the previous group is printed unless week wrapping is in effect. Finally when all the days are processed the last group is adjusted for any week wrapping and whether all the hours turned out to be the same before being output. 0 is used as a placeholder because empty strings cost more bytes to compare in Batch.

Jelly, 87 84 80 75 bytes

4bytes with the kind help of @Dennis (fixed a hack I used with the ' quick, "flat")

Pretty sure there is a better way but for now:
Ṫ2ị$€;@µ+\µżṙ1’$Ṗị“ḅạṄMḤ9\E¥LḃɓṅÐĿ;$»s3¤Q€j€”-
ṙ7Ḷ¤Œr'€Ėµ2ịLµÐṂḢ
ÇṪḢ€ż@ÇÑ$G

TryiItOnline
How?
            “ḅạṄMḤ9\E¥LḃɓṅÐĿ;$» - compressed string "montuewedthufrisatsun"
                  v  v
Ṫ2ị$€;@µ+\µżṙ1’$Ṗị -- s3¤Q€j€”- - Link 1, getDayStrings: [offset, groupedList]
Ṫ                               - Tail: get groupedList
 2ị$€                           - second index of each: get group sizes, e.g. mon-thu is 4
     ;@                         - concatenate (reversed arguments): prepend with offset
       µ                        - monadic chain separation
        +\                      - cumulative reduce with addition: start indexes
          µ                     - monadic chain separation
           ż                    - zip with
               $                - last two links as a monad
            ṙ1                  -     rotated left by one
              ’                 -     decrement:  end indexes
                Ṗ               - pop: remove last one, it's circular
                 ị              - index into
                        ¤       - last two links as a nilad
                    --          -     compressed string of weekdays (as shown at the top)
                      s3        -     split into 3s
                        Q€      - unique items for each: [tue,tue] -> [tue]
                          j€    - join each with
                            ”-  - literal string "-"

ṙ7Ḷ¤Œr'€Ėµ2ịLµÐṂḢ - Link 2: CalculateGroupingData: list of time strings
   ¤              - last two links as a nilad
ṙ                 -    rotate time strings list left by
 7Ḷ               -    range 7: [0,1,2,3,4,5,6]
       €          - for each
    Œr            -     run length encode
      '           -     flat - i.e. don't vectorise
        Ė         - enumerate [[1,[groupsFromMon]],[2,[groupsFromTue], ...]
         µ        - monadic chain separation
              ÐṂ  - filter for minimum of
             L    -     length of
          2ị      -     item at index 2: The number of groupings
                Ḣ - head: get the first occurring minimal (i.e Mon, or Tue, ...)

ÇṪḢ€ż@ÇÑ$G - Main link: list of time strings
Ç          - call last link (1) as a monad: get the offset and grouping
 Ṫ         - tail: get the grouping
  Ḣ€       - head each: get the time information
        $  - last two links as a monad
      Ç    -      call last link (1) as a monad: get the offset and grouping
       Ñ   -      call the next link as a monad: get the day strings
    ż@     - zip (with reversed arguments)
         G - arrange as a group (performs a tabulation to nicely align the result)

JavaScript (ES6), 171 169 bytes
a=>a.map((e,d)=>(d='montuewedthufrisatsun'.substr(d*3,3),e!=h&&(f?o(f):w=l,f=d,h=e),l=d),f='',l=w='sun',h=a[6],o=f=>console.log((f==l?l:f+'-'+l)+' '+h))&&o(f||'mon',l=w)

Takes input as an array and outputs to the console on separate lines. This is almost exactly a port of my Batch answer; f now defaults to an empty string of course, while I can also default l and w to 'sun' (using a sentinel value saved me 3 bytes in Batch because I was able to merge the initialisation into the set/a).

BaCon, 514 496 455 bytes
The BASIC program below is shown with its indentation. But without the indentation it consists of 455 bytes.
The idea is to use the time schedules as indexes to an associative array. Then, each day represents a bit: Monday = bit 0, Tuesday = bit 1, Wednesday = bit 2 and so on. The actual values for the members of the associative array are calculated by the respective bits of the days using a binary OR.
After that, it is a matter of checking how many consecutive bits are present in the associative array members, starting with bit 0.
In case bit 0 and also bit 6 are set, there is a week wrap. In that case, start looking for the start of the next sequence of bits, memorizing this start position. Print the rest of the sequences, and as soon bit 6 is reached, the day range should be ended with the memorized position earlier.
LOCAL n$[]={"mon","tue","wed","thu","fri","sat","sun"}
GLOBAL p ASSOC int
SUB s(VAR t$ SIZE a)
    FOR i = 0 TO a-1
        p(t$[i])=p(t$[i])|BIT(i)
    NEXT
    LOOKUP p TO c$ SIZE o
    b=e=0
    REPEAT
        FOR i=0 TO o-1
            IF p(c$[i])&BIT(b) THEN
                IF b=0 AND p(c$[i])&65=65 THEN
                    WHILE p(c$[i])&BIT(b)
                        INCR b
                    WEND
                    e=b
                    BREAK
                FI
                ?n$[b];
                r=b
                REPEAT
                    INCR b
                UNTIL NOT(p(c$[i])&BIT(b))
                IF e AND b>6 THEN
                    ?"-",n$[e-1];
                ELIF b-r>1 THEN
                    ?"-",n$[b-1];
                FI
                ?" ",c$[i]
            FI
        NEXT
    UNTIL b>6
    FREE p
ENDSUB

Using the following calls to invoke the SUB:
s("0900-1800", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500", "1100-1500")
PRINT "======"
s("0900-1800", "0900-1800", "0900-1800", "0930-1700", "0900-1800", "1100-1500", "1100-1500")
PRINT "======"
s("1100-1500", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500", "1100-1500")
PRINT "======"
s("1100-1500", "1100-1500", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500")
PRINT "======"
s("1200-1500", "1100-1500", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500")

Output:
mon-fri 0900-1800
sat-sun 1100-1500
======
mon-wed 0900-1800
thu 0930-1700
fri 0900-1800
sat-sun 1100-1500
======
tue-fri 0900-1800
sat-mon 1100-1500
======
wed-sat 0900-1800
sun-tue 1100-1500
======
mon 1200-1500
tue 1100-1500
wed-sat 0900-1800
sun 1100-1500


text:
ASCII PPCG Beta Logo Golf
We shall soon have a new logo & site design, let us use this last breath of the simple times and golf this ASCII version of the speech bubble beta logo:
+-------------------------------------------+
|    .---------------------------------.    |
|   .EPEpEpBPEpEGCXCgCgCGJgCgP&PWP&P&P&Y`   |
|  .RSRsRWRSRsRsHoNoNONxNONONuJuSUSUSVSUS`  |
|  :o@OTO@O@O@W@IDiDIWiDIDIDWZEZeZEWEZeZE-  |
|  :GWGFGfGFKFGFMEMwMEMEMeXEMZLZLWLZLzLZH-  |
|  :rLRLRLXLRLrLMBMGMGmGXGMGMLzTZLZLZLYLZ-  |
|  :AOAoBOAOAOAYAOAoAoBOAOAoAWZEZEZEVEZEZ-  |
|  :MGVGm!'""'!GRLr!'""'!LRKRS!'""'!uSuSU-  |
|  :XEME' .''% !Gf' .;G% 'GFG' .;P% '&PVP-  |
|  :IDID  !DI! !V! .OPoYOPOP!  -gCGCGHGCG-  |
|  :NONw  ``` .OR! .RWRRRRRR! !ONo* 'ONON-  |
|  :GBGC  !CXCGCP! !POP; !xOP  `IJ; `!IDW-  |
|  :P&P&._!&P&P&F~.____.;GFGF~.____.;eJEM-  |
|  :USUSVSUSuSuTLRlRLRWRLRlRLWMGMGmGwGmGM-  |
|  :ZeWEZEZeZWZeOAOaKAOAOaOwOOAoAOXoAoAOA-  |
|  :wLZLZLzHZLZLGMxMgMGMgBGMGLRLXLRLrLRTr-  |
|  :LZLZLYLZLZLzBMEMEMEyEmEMEfBFGFGfGWGFG-  |
|  :EZEVEZEZeZVZDIdIDYdIdIDIx@O@o@oKO@O@o-  |
|  `SkSuSuSUXUSuONOVONOnONWNOSRSRWRSRSRS-   |
|   `.&P&PVP&P&PCXcGCGCGVGcGCEPYPEpEPE?.-   |
|      ```````````````````:STACKE-`````     |
|                         :XCHA-`           |
|                         :NG-`             |
|           ?=W...HWYWVWB :E`               |
+-------------------------------------------+

This is kolmogorov-complexity code-golf, so it's straight forward, output all the text that appears in the above code-block in as few bytes of code as possible, without any funny-business.
input
None
Output
The ASCII content of the code-block above as a return value or printed to STDOUT or equivalent;
carriage returns (13) and/or new lines (10) are acceptable;
a trailing empty line is also allowed.
Update
The original aim of this challenge was to have a puzzle aspect. It seems this has not been noticed, so I have decided to make the puzzle portion significantly easier, but still present, by performing a couple of steps to get you going:

There is a use of the string "STACKEXCHANGE" in the very bottom portion of the speech-bubble.
If one reads the rows of text in the main-portion of the speech-bubble, one might notice an almost repetitive nature of pairs of letters, for example the fourth row reads "GWGFGfGFKFGFMEMwMEMEMeXEMZLZLWLZLzLZH" which is almost "GFGFGFGFGFGFMEMEMEMEMEMEMZLZLZLZLZLZH", except some letters have been changed either to another letter (e.g. the second letter from F to W), to lower-case (e.g. the sixth letter from F to f), or both (e.g. the sixteenth letter from E to w). The rows seem to all conform to such a pattern with a 12-13-12 character split (ignoring the mess of the PPG logo's white space and border).
The process described in (2), once noticed, should be quite easy to undo for the unmasked rows of the speech-bubble (the top six and bottom seven), by first converting the whole text to upper-case and then replacing the odd-ones-out and results in:

+-------------------------------------------+
|    .---------------------------------.    |
|   .EPEPEPEPEPEGCGCGCGCGCGCGP&P&P&P&P&P`   |
|  .RSRSRSRSRSRSNONONONONONONUSUSUSUSUSUS`  |
|  :O@OTO@O@O@O@IDIDIWIDIDIDIZEZEZEZEZEZE-  |
|  :GFGFGFGFGFGFMEMEMEMEMEMEMZLZLZLZLZLZL-  |
|  :RLRLRLRLRLRLMGMGMGMGMGMGMLZLZLZLZLZLZ-  |
|  :AOAOAOAOAOAOAOAOAOBOAOAOAEZEZEZEZEZEZ-  |
|  :MGVGm!'""'!GRLr!'""'!LRKRS!'""'!uSuSU-  |
|  :XEME' .''% !Gf' .;G% 'GFG' .;P% '&PVP-  |
|  :IDID  !DI! !V! .OPoYOPOP!  -gCGCGHGCG-  |
|  :NONw  ``` .OR! .RWRRRRRR! !ONo* 'ONON-  |
|  :GBGC  !CXCGCP! !POP; !xOP  `IJ; `!IDW-  |
|  :P&P&._!&P&P&F~.____.;GFGF~.____.;eJEM-  |
|  :USUSUSUSUSURLRLRLRLRLRLRLGMGMGMGMGMGM-  |
|  :ZEZEZEZEZEZEOAOAOAOAOAOAOOAOAOAOAOAOA-  |
|  :ZLZLZLZLZLZLGMGMGMGMGMGMGLRLRLRLRLRLR-  |
|  :LZLZLZLZLZLZEMEMEMEMEMEMEFGFGFGFGFGFG-  |
|  :EZEZEZEZEZEZDIDIDIDIDIDID@O@O@O@O@O@O-  |
|  `SUSUSUSUSUSUONONONONONONOSRSRSRSRSRS-   |
|   `.&P&P&P&P&PCGCGCGCGCGCGCEPEPEPEPEP.-   |
|      ```````````````````:STACKE-`````     |
|                         :XCHA-`           |
|                         :NG-`             |
|           ?=W...HWYWVWB :E`               |
+-------------------------------------------+

While carrying out (3) one may notice a couple of things. First the least obvious: that the only ?, in the very bottom-right became a P, whereas the extra text at the bottom says ?=W..., and that a large proportion of replaced characters were also W. Second that the odd-ones out in upper-case were B,H,J,K,T,V,W,X,Y. Third that the odd-ones out occurred every seven letters. The second and third observation helps to fill in the middle rows - which, if we remove the PCG mask of spaces and non-letters, non & (used in the top and bottom row) and replace it with the letters yields:

+-------------------------------------------+
|    .---------------------------------.    |
|   .EPEPEPEPEPEGCGCGCGCGCGCGP&P&P&P&P&P`   |
|  .RSRSRSRSRSRSNONONONONONONUSUSUSUSUSUS`  |
|  :O@O@O@O@O@O@IDIDIWIDIDIDIZEZEZEZEZEZE-  |
|  :GFGFGFGFGFGFMEMEMEMEMEMEMZLZLZLZLZLZL-  |
|  :RLRLRLRLRLRLMGMGMGMGMGMGMLZLZLZLZLZLZ-  |
|  :AOAOAOAOAOAOAOAOAOBOAOAOAEZEZEZEZEZEZ-  |
|  :MGMGMGMGMGMGRLRLRLRLRLRLRSUSUSUSUSUSU-  |
|  :MEMEMEMEMEMEGFGFGFGFGFGFG&P&P&P&P&P&P-  |
|  :IDIDIDIDIDIDOPOPOPOPOPOPOCGCGCGCGCGCG-  |
|  :NONONONONONORRRRRRRRRRRRRONONONONONON-  |
|  :GCGCGCGCGCGCPOPOPOPOPOPOPDIDIDIDIDIDI-  |
|  :P&P&P&P&P&P&FGFGFGFGFGFGFEMEMEMEMEMEM-  |
|  :USUSUSUSUSURLRLRLRLRLRLRLGMGMGMGMGMGM-  |
|  :ZEZEZEZEZEZEOAOAOAOAOAOAOOAOAOAOAOAOA-  |
|  :ZLZLZLZLZLZLGMGMGMGMGMGMGLRLRLRLRLRLR-  |
|  :LZLZLZLZLZLZEMEMEMEMEMEMEFGFGFGFGFGFG-  |
|  :EZEZEZEZEZEZDIDIDIDIDIDID@O@O@O@O@O@O-  |
|  `SUSUSUSUSUSUONONONONONONOSRSRSRSRSRS-   |
|   `.&P&P&P&P&PCGCGCGCGCGCGCEPEPEPEPEP.-   |
|      ```````````````````:STACKE-`````     |
|                         :XCHA-`           |
|                         :NG-`             |
|           ?=W...HWYWVWB :E`               |
+-------------------------------------------+

Now reading the columns one can see that the "input" text to make this base grid was PROGRAMMINGPUZZLES&CODEGOLFPROGRAMMINGPUZZLES&CODEGOLF@SE.

The lower-casing and replacement characters are to be determined by you, but also note that the ten remaining letters in the alphabet after removing those present in that string are B,H,J,K,Q,T,V,W,X,Y - the replacements plus Q.

Kind of related.

Just wondering, how did you generate this?

@Oliver Python and Notepad++. Part of the puzzle is to find any patterns in the data of course (although I cannot say if a pure compression will triumph).

@Downvoters Can you please explain the downvotes?

@TùxCräftîñg they probably think it looks too random? Or maybe my art is no good .

Are trailing spaces allowed?

I downvoted because ASCII-art challenges should have some pattern or sequence (same with kolmogorov-complexity), but this is an arbitrary image which isn't even a proper ASCII representation of the PPCG logo, nor does it even use a consistent pattern of characters

@Downgoat there is pattern to the majority of the characters. I thought part of the challenge of kolmogorov-complexity was to find those patterns.

@daHugLenny - At present, no, I have specified one trailing \n, \r or pair of the two, but if there is a valid reason why it would be necessary in some set of languages I would, of course, consider it; let me know.

@JonathanAllan At that point this challenge might be better suited for puzzling.

@ConorO'Brien - I actually said the same myself. But note that the [tag:kolmogorov-complexity] info does say "The output will preferably have non-obvious and unknown patterns. The challenge of Kolmogorov complexity is mainly to find those patterns". Also I think it just might be possible using a golfing language in less than the Bubblegum answer if one finds and exploits those patterns.

the line at the bottom definitely isn't in the logo.

@ricyje you are correct.

"We shall soon have a new logo & site design" Ahahahahahahah. ha. haha. ha

@Geobits - before anyone finds the hidden pattern it seems.

Bubblegum, 542 541 bytes
Reversible hexdump:
00000000: d2d6 251e 68f3 72d5 002a 2903 1637 6138  ..%.h.r..*)..7a8
00000010: 8a7f 9578 7027 0c9a 0fd0 32ae 6a63 b435  ...xp'....2.jc.5
00000020: 2668 6734 00e7 d8d9 32b6 cea3 4769 57c6  &hg4....2...GiW.
00000030: 3efb 5e94 1a60 07c7 e5f1 7f89 f033 35ff  >.^..`.......35.
00000040: a725 18f4 5d92 5aec cf88 53a6 d80b 7b09  .%..].Z...S...{.
00000050: adf3 a88e f610 5fc3 d583 d228 a869 279c  ......_....(.i'.
00000060: 1665 f15a e8c1 5f93 3eef 7399 5f72 099d  .e.Z.._.>.s._r..
00000070: d6a7 f20b 54a1 da1b 3eef 9772 2b97 567a  ....T...>..r+.Vz
00000080: 99ae beaf 528d 82b4 61a6 334c 0f3e 9b70  ....R...a.3L.>.p
00000090: ae79 cc77 3cde c43c 164c 9c05 83ba 9a09  .y.w<..<.L......
000000a0: 9399 4ca3 ae99 491c 7ecc 0aa8 461d 3311  ..L...I.~...F.3.
000000b0: 0a2e f881 d770 915d b7b8 036a 32e3 f040  .....p.]...j2..@
000000c0: 067d 2803 ab06 d58f 5798 b561 5695 7587  .}(.....W..aV.u.
000000d0: 0b5e f183 e7df ddf9 1ec7 2f8c abac d814  .^......../.....
000000e0: e5b8 3c95 38b1 c3f1 94cc 27d4 f7ef 89c7  ..<.8.....'.....
000000f0: 7758 2df8 3df1 711e bb54 583e a84a 39dc  wX-.=.q..TX>.J9.
00000100: 7681 106f 957a c4ab 3c42 a5ea 1ba9 a4f2  v..o.z..<B......
00000110: 0899 2181 8827 2887 a3c3 6742 dab6 0559  ..!..'(...gB...Y
00000120: 0047 06c3 c0dd 32ef 3f11 5f82 7038 0f79  .G....2.?._.p8.y
00000130: 84dd a31a 3b29 30d8 7841 bc8b 54d8 235d  ....;)0.xA..T.#]
00000140: 2f48 eb21 0387 db94 e993 37a4 1dff a54f  /H.!......7....O
00000150: 1878 fc98 4feb 6ecd 84c3 6f39 a303 dbac  .x..O.n...o9....
00000160: f889 1034 0ab3 1e33 38a3 84c3 4da7 d990  ...4...38...M...
00000170: b736 1d1a fe75 1358 9767 697b 2feb de7a  .6...u.X.gi{/..z
00000180: e0f0 f390 dc35 b1ce c545 ecb1 e93e c4c6  .....5...E...>..
00000190: 53d6 c5f6 e8f0 5bce d035 14cc ea37 3bc0  S.....[..5...7;.
000001a0: 7761 3cbc 4d1a eef0 5bce 9da9 cc2a 7d4e  wa<.M...[....*}N
000001b0: 57cd b3f5 f482 77b4 5ff6 1b69 e709 6fcb  W.....w._..i..o.
000001c0: 1fe5 9073 8dd3 a2c5 15ea 97cc 752e 4b7c  ...s........u.K|
000001d0: 031a 0581 1e71 f014 1d44 ced6 a3fa 1b8f  .....q...D......
000001e0: a08a 6366 aab1 5f98 628f d4e1 76b4 ff8f  ..cf.._.b...v...
000001f0: 79b9 0da2 0d9b 0d17 401c fee6 98d7 5112  y.......@.....Q.
00000200: ccda e9fa 3d3c e70e 7e0b 7ffc ac29 a589  ....=<..~....)..
00000210: 6e74 a543 34cc c113 fea1 bfa5 7f         nt.C4........

Try it online!
Just Zopfli'd the string for 1 million iterations. Running for 100 million iterations does not yield a shorter solution.

PHP, 780 Bytes
<?=gzinflate(base64_decode("lZRvb9owEMbfT9p3cCq1kYbiDwCaShIcE0hiK2FxkjdNtQY0bSwVVQVDVT/7HpuBYZv2x6e7XKKfD/sem4H372Pw9s0LwaB/JanGXg44ZZI9ssdARx5W4QrGZ4jyRio4rG5POM2L/ClXJj5N+6zPRLaDi+x59lx8gJXw9ogP+7FYiLE2NY4nnyaxgsNUw5quYcpE74RzxSO+5NE84lHK0i2cpV3F0iZpEgXfJ83U4pskh1XwTZIGKU/5mleIabJf6BlNUieNxX3h94HwtdU6//HW+3o1sFJHi6e85GvHvbpyHY5fOGRJPs+LQ/pcYMcWxyqZS6jrXhOHL5GN+DVxsR+dSqQ3spQW110gxJnEDnFKh1Ah+1pIIR1CPCgQ8inc4ujwlpC2bUHmwKGBGZgtsv4dcbUGZ40MeIjq0JOHKOmg8Ig4OyFRI56NSOtAA4trlemdY9SOXukdBpYPEY55N2OpxY86owOLJP8CEVRunuqgwRZ+hjedYkZv1XRo+P1cS3AvtkL3XlS9jr7Ft0a5/VRHnu7SFYquAhQ+aZ0vNhY/6qznBObAsG9sjbgMInOa9Jmy+FHnrimbSfwQT+oHHeMdzmg/7uf6rPYnvC0+F0bnCrtFi0v4V5GpTBS4A/oewDx7m1qqe1iaexNWH7kWsuR4MlnrGybZLT3DiZH05zEsFn44Z555IeQC/80YVuHU99qzL3/GM34B/4LfvleU0qmqVakCNOwSNvjgf/6WvgM="));

Maybe helpful maybe not I do not know
I give up to find an other way.
beginning the first line at 1
you could concat lines they have the sum 24 with one letter
starts with the W in the middle go up go left and go reverse the 2 line down then concat the first letter of line 13 with the end of line 11 and go to the middle
now I assume that you must go down to line 14
It seems for me that "?=W...HWYWVWB" is a hint to solve this

Thanks for taking the effort to look for patterns! Indeed the extra text at the bottom is part of a pre-golf puzzle. I am in the process of updating the question to give some more insight...

@JonathanAllan Could it been that my feeling that I can read "I DID IT ON PCG" is right?

No, I saw that too :D. My upcoming update will get you the "input" text...

Ruby, 788 bytes
Basically the same method as the PHP solution.
puts Zlib.inflate Base64.decode64 "eJyVlG9vmzAQxt/vU5hKLdIi/AESTQ0QxyEBjCDDwJtSrUk0bRlVqihZVfWz7zmnOG017Y9PdxzRzyf83DkD79/X4MMTw+J/BTlhT4bmIhP34j6gKMMq3MDkHDG7yjQcVrc9zfMif8i1iQ+zLu1SlR7hKt3P98VnWAlvX+hhN1ZLNSbT42jydRJpOEw3olk1Qpvo9bTUcirXcrqYymkikgNcJKtKJE3cxBr+GDczS+/iHFbBd3ESJDKRW1khJvHjkjY0cR03lvaV3wXKJ6spf3nrfPoUWEnR0oks5dZxLy5cR6L+KYvzRV6c0n2Bw1oaXyhcxl33kjlyjWwkL5mLs1CaIb3KyszSdH7GnEnkMKd0GFdZV6tMZQ5jHpQP5QxuaSh7YKxtW4A5aGhvFjartPvIXNL+rGAgQ9RGF2WIgg7KjphzVBlKRPMRax1ob2lqLb9xTIunz/wGC58O8ft8NReJpfvm4uzLOP8O8XVunvqk/QF+ppuVFqbJullB6NsFSX+rDoo0V1VH0bf0wfTrcUZRJsdkg5KbAGVth/PlztJ9c2lLYIZE/BRbxHUwNRNEc2Tpvrmrpmwm0V00qe8oRkdMZTfuFjSdXU+3xbfCNLfCQSFtCf+hUp2qAjNPcw/z7N1pOYlXmlsSVl8kta+UeIqspvuUiWt+pplp5Ps1LJZ+uBCeeWHsNf2bNazCme+1r375I53KN+x7+vqT5pzPdK1LHUCqtyzRg//69/kFnIsxTA=="