# Would this string work as string?

Write a program that takes a single line string that you can assume will only contain the characters /\_‾. (That's forward and backward slash, underline and overline. You can use ~ in place of overline if you need since overline is not convenient ASCII.)

For example, one possible input is:

__/‾‾\/\_/‾

Your program needs to output a truthy or falsy value depending on whether the left edge of the string is "connected", so to speak, to the right edge of the string via the lines of the characters. So, if the kerning was a bit less, there would be a solid black (albeit kinky) line all the way from the left edge to the right, like an unbroken piece of string or twine.

The output for the above example would be true because the edges are connected:

To be clear on the connections:

• / connects on its bottom left and top right
• \ connects on its top left and bottom right
• _ connects on its bottom left and bottom right
• (or ~) connects on its top left and top right

Also:

• It doesn't matter whether the edges of the string started on the top or the bottom, it only matters that they connect horizontally through the whole length of the string.

• You can assume the input string is non-empty, and of course just one line.

Here are some more examples followed by 1 (truthy) if they are connected or 0 (falsy) if not:

__/‾‾\/\_/‾
1

_
1

\
1

/
1

‾
1

___
1

\/
1

/\/
1

/\/\
1

‾‾‾
1

\\
0

‾‾
1

_‾
0

‾_
0

\_____/
1

\/\\/\\___
0

\/\__/‾‾\
1

______/\_____
1

‾‾‾‾‾‾\\_____
0

‾‾‾‾‾‾\______
1

_____/‾‾‾‾‾
1

\___/‾‾‾\___/‾‾‾
1

\_/_\_
0

\_/\_
1

/\/\/\/\/\/\/\/\/\/\/\/
1

____________________
1

‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
1

‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾/
0

‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾\
1

/\‾/\‾___/\_\/__\/\‾‾
0

The shortest code is the winner.

• Welcome to PPCG! Nice first challenge. Mar 18 '19 at 15:30
• Are the characters specified in your challenge the only ones that will appear in the string? Mar 18 '19 at 15:31
• @EmbodimentofIgnorance Yes, only the 4. Mar 18 '19 at 15:34
• Wait you could make a language out of this Mar 18 '19 at 18:57
• @Arnauld No, I really think only truthy for connected and falsy for unconnected. (Unless allowing a swap is normal for this kind of question?) Mar 19 '19 at 4:35

# Jelly, 9 bytes

-1 byte thanks to @EriktheOutgolfer

Expect ~ instead of . Returns $$\0$/extract_tex] or $$\1$$/extract_tex]. O*Ɲ:⁽8ƇḂẠ Using this formula (but otherwise similar to the 11-byte version below): $$n=\left\lfloor\frac{x^y}{15145}\right\rfloor$$ The transition is valid if $$\n\$$ is odd, or invalid if $$\n\$$ is even. ### Commented O*Ɲ:⁽8ƇḂẠ - main link, taking a string e.g. "\_/" O - get ASCII codes --> [92, 95, 47] *Ɲ - exponentiation on all pairs --> [92**95, 95**47] :⁽8Ƈ - integer division by 15145 --> [23964828…8421, 59257069…0485] Ḃ - least significant bit (i.e. parity) --> [1, 1] Ạ - all values equal to 1? --> 1 # Jelly, 14 12 11 bytes Supports (and expects) the character in the input string. Returns $$\0\$$ or $$\1\$$. O*Ɲ%276%7ỊẠ ### How? Given two consecutive characters of ASCII codes $$\x\$$ and $$\y\$$, we want a function that checks whether they form a valid transition. We need a non-commutative operation, because the result may change when the characters are reversed. For instance, _/ is valid but /_ is not. Using exponentiation, a possible formula1 is: $$n=(x^y \bmod 276)\bmod 7$$ The transition is valid if $$\n\le1\$$, or invalid if $$\n>1\$$. chars | x | y | (x**y)%276 | %7 | valid -------+------+------+------------+----+------- __ | 95 | 95 | 71 | 1 | yes _/ | 95 | 47 | 119 | 0 | yes _‾ | 95 | 8254 | 265 | 6 | no _\ | 95 | 92 | 265 | 6 | no /_ | 47 | 95 | 47 | 5 | no // | 47 | 47 | 47 | 5 | no /‾ | 47 | 8254 | 1 | 1 | yes /\ | 47 | 92 | 1 | 1 | yes ‾_ | 8254 | 95 | 136 | 3 | no ‾/ | 8254 | 47 | 88 | 4 | no ‾‾ | 8254 | 8254 | 196 | 0 | yes ‾\ | 8254 | 92 | 196 | 0 | yes \_ | 92 | 95 | 92 | 1 | yes \/ | 92 | 47 | 92 | 1 | yes \‾ | 92 | 8254 | 184 | 2 | no \\ | 92 | 92 | 184 | 2 | no 1. Found with a brute-force search in Node.js (using BigInts) ### Commented O*Ɲ%276%7ỊẠ - main link, taking a string e.g. "\_/" O - get ASCII codes --> [92, 95, 47] *Ɲ - exponentiation on all pairs --> [92**95, 95**47] %276 - modulo 276 --> [92, 119] %7 - modulo 7 --> [1, 0] Ị - ≤1? --> [1, 1] Ạ - all values equal to 1? --> 1 • lookup table method has won many a problem – qwr Mar 18 '19 at 20:29 • 9 bytes: ⁽"O is the same as 9580. Mar 18 '19 at 22:32 • @EriktheOutgolfer Thanks. :) Maybe the script provided in this tip should be updated to support this format (when it's relevant). Mar 18 '19 at 22:49 • @Arnauld Actually, Jonathan Allan has made this. Mar 18 '19 at 22:56 # Ruby -n, 30 bytes p !/[_\$[\\‾]|[\/‾][_\/]/ Try it online! Reduces all of the string-breaking sequences to two cases using Regex character classes. • You can save 4 bytes by using ~ instead of . I'm not sure if it matters for this challenge, since the character count is the same. Mar 18 '19 at 16:32 • Do you need to escape the /s even though they are within square brackets? Mar 18 '19 at 22:59 # JavaScript (ES6), 45 bytes The naive way. s=>!/\/\/|\\\\|_~|~_|~\/|_\\|\/_|\\~/.test(s) Try it online! • So this is checking all the invalid pairings, making sure they don't exist in the string? Smart. Mar 18 '19 at 15:47 • @DiscreteGames Yes, exactly. (Except that I forgot 2 of them. Now fixed.) Mar 18 '19 at 15:50 • 35 bytes: s=>!/[~\/][\/_]|[_\$$[\\~]/.test(s). It checks if \/ or ~ end in \/ or _. And then, it check if \\ or _ end in \\ or ~. Mar 21 '19 at 13:02
• @IsmaelMiguel This might be posted as a separate answer, but I'd better leave this one unchanged for reference, as it shows the simplest (as in 'least complicated') regular expression solving the problem. Mar 21 '19 at 13:05
• You can post it as an alternative, but not definitive answer. Mar 21 '19 at 15:28

# Python, 46 bytes

f=lambda s:s==''or s[:2]in"__/~~\/\_"*f(s[1:])

Try it online!

TIO

26 bytes

# R, 43 chars, 47 bytes

It's the same regex the other answers use, but adapted for R.

!grepl('[/‾][/_]|[\\\\_][\\\\‾]',scan(,''))

Try it online!

And obligatory xkcd.

• you can use ~ in place of to get to 43 bytes, 43 chars. Mar 18 '19 at 19:50
• True, but it's more fun with the overbar. :) Mar 18 '19 at 19:57

# Forth (gforth), 100 98 bytes

: x = swap '~ = + ;
: f 1 tuck ?do over i + >r i 1- c@ r> c@ dup 92 x swap dup 47 x <> + loop 0> ;

Try it online!

### Explanation

Go through the string and determine whether each character starts on the same position (top or bottom) as the one before ends. Subtract 1 from a counter if they don't match. At the end, if the counter has changed, then the string is not a string.

End position is high if char is / (47) or ~ (126). Otherwise it's low

Start Position is high if char is \ (92) or ~ (126). Otherwise it's low

### Code Explanation

\ x is basically just extracting some common logic out into a function to save a few bytes
\ it checks if the first number is equal to the second number
\ or the third number is equal to 126
: x                \ start a new word definition
= swap           \ check if the first two numbers are equal then swap with the third
'~ =             \ checks if the third number is equal to 126
+                \ adds results together (cheaper version of or)
;                  \ end the word definition

: f                \ start a new word definition
1 tuck           \ set up parameters for a loop (and create a bool/counter)
?do              \ start counted loop from 1 to string-length -1,
\ ?do will skip if loop start and end are the same
over i +       \ copy the string address and add the loop index to get the char address
>r i           \ place char address on return stack and place a copy back on the stack
1- c@          \ subtract 1 to get previous char address and grab ascii from memory
r> c@          \ move char address back from return stack, then grab from memory
dup 92 x       \ get the "output" position of the prev character
swap dup 47 x  \ get the input position of the current character
<> +           \ check if they aren't equal and add the result to the counter
\ the counter won't change if they're equal
loop             \ end the loop
0>               \ check if counter is less than 1 (any of the "links" was not valid)
;                  \ end word definition

# C (gcc), 41 36 bytes

f(char*_){_=!_[1]||*_/32+*++_&f(_);}

Try it online!

-5 eliminated &1 starting off from an idea from Peter Cordes; changed operators (precedence) to remove parentheses

Uses ~. Checks the first and sixth bits of the first two characters' binary representations:

_ 1011111
\ 1011100
/  101111
~ 1111110
^    ^

and traverses the string recursively.

(*_ / 32) & 1 is true only for chars that end high, while *_ & 1 is true only for chars that start low. (x&1) ^ (y&1) == (x+y)&1. XOR is add-without-carry, and carry doesn't disturb the lowest bit. The 1 comes from the f(_) return value, if the rest of the string was stringy.

• Right shifting by 5 leaves the 6th bit at the bottom. So you're checking bits 0 and 5, or the first and sixth bits. (This is a really nice trick, BTW, well done. c&32 is true for chars that end high, while c&1 is true only for chars that start low.) Mar 19 '19 at 22:04
• I know the rules only require it to work on at least one implementation, but still worth pointing out that *_ ^ *++_ is undefined behaviour: ^ is not a sequence point, so there's no sequenced-before relationship guaranteeing they get different characters. Of course it's also missing a return, so it only works with gcc -O0 where the function body is a statement-expression. Mar 19 '19 at 22:09
• Oops, you're right about the bits. Thanks for catching that
– att
Mar 19 '19 at 22:31
• Doing &1 twice is redundant. (x^y)&1 == (x&1) ^ (y&1). But given C operator precedence where & has higher priority than ^ (unlike arithmetic operators where + and - have the same priority), we'd need to add () 2 bytes to remove &1 2 bytes, because (x&1) ^ y is not equivalent. But maybe using parens opens up opportunities for some other saving. Fortunately not a problem for an x86 machine-code version of this, where the bit manipulation is very compact... Mar 19 '19 at 22:39
• Finished my x86 machine code answer, 13 bytes using this algorithm. Mar 20 '19 at 2:29

# Python 3, 80 78 bytes

I don't realy do many python code golfs but I thought I could give it a try

• -2 bytes: realised not(any()) is the same as all(not()) and could move the not into the r-string
def f(x):*l,=map(r'_/\~'.find,x);return 1-any((i^j//2)%2for i,j in zip(l,l[1:]))

Try it online!

# Python 3.8 (pre-release), 71 bytes

I wanted to try out the new := expression assignment

lambda x:all((i^j//2)%2for i,j in zip(l:=[*map(r'\~_/'.find,x)],l[1:]))

Try it online!

# Excel, 150 bytes

=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(A1,"_\",),"_‾",),"‾_",),"‾/",),"/_",),"//",),"\‾",),"\\",)=A1

Removes any invalid pairs, then return true if this results in the original string.

g=tail>>=zip
h=all(elemg"__/~~\\/\\_").g

this solution uses ~, and the function to call is h (i.e., h string gives the answer)

The solution uses a function g that given a list, returns all tuples of adjacent values on the list.

Then we use g to generate the list of allowed neighbors (in g"__/~~\\/\\_") and also the list of all neighboring pairs in the input list. Then we check that each neighboring pair is an allowed pair.

# Bash, 30 bytes

grep -E '//|\\\\|_~|~_|~/|_\\|/_|\\~'

Input is STDIN. Exit code is 1 if valid, 0 if invalid.

# SNOBOL4 (CSNOBOL4), 58 bytes

INPUT '/_' | '_\' | '\\' | '//' | '~/' | '\~' @OUTPUT
END

Try it online!

Outputs nothing for truthy and a positive integer (indicating the position of the first break in the string) for falsy.

# Charcoal, 32 18 bytes

⌊⭆θ∨¬κ⁼№_/ι№\_§θ⊖κ

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

θ                 Input string
⭆                  Map over characters and convert to string
κ              Current index
¬               Logical Not (i.e. is zero)
∨                Logical Or
ι         Current character
№            Count (i.e. contained in)
_/          Literal _/ (i.e. begins at bottom)
⁼             Equals
θ    Input string
§     Indexed by
κ  Current index
⊖   Decremented (i.e. previous character)
№        Count (i.e. contained in)
\_      Literal \_ (i.e. ended at bottom)
⌊                   Minimum (i.e. if all true)
Implicitly print

# x86 machine code, 13 bytes.

(Or 11 bytes without handling single-character strings that are trivially stringy.)

Uses the bit-position check from @attinat's C answer

Same machine code works in 16, 32, and 64-bit modes. The source is NASM for 64-bit mode.

nasm -felf64 -l/dev/stdout  listing
18           code          string_connected:
19           bytes         ;;; input: char *RSI, transitions to check=RCX
20                         ;;; output: AL=non-zero => connected.  AL=zero disconnected
21                         .loop:                      ; do {
22 00000000 AC                 lodsb                   ;   al = *p++
23 00000001 E309               jrcxz  .early_exit        ; transitions=0 special case.  Checking before the loop would require extra code to set AL.
24 00000003 C0E805             shr    al, 5
25 00000006 3206               xor    al, [rsi]          ; compare with next char
26 00000008 2401               and    al, 1
27 0000000A E0F4               loopne .loop            ; }while(--rcx && al&1);
28                         .early_exit:
29 0000000C C3                 ret

Callable from C as unsigned char string_connected(int dummy_rdi, const char *s, int dummy_rdx, size_t transitions); with the x86-64 System V calling convention. Not bool because the transitions=0 case returns an ASCII code, not 1.

RCX = len = strlen(s) - 1. i.e. the number of character-boundaries = transitions to check in the explicit-length string.

For transitions > 0, returns 0 (mismatch) or 1 (connected) and leaves ZF set accordingly. For transitions == 0, returns the single byte of the string (which is non-zero and thus also truthy). If not for that special case, we could drop the early-exit JRCXZ. It's inside the loop only because AL is non-zero there.

The bit-position logic is based on the observation that bit 0 of the ASCII code tells you the starting height, and bit 5 tells you the ending height.

;;;  _ 1011111
;;;  \ 1011100
;;;  /  101111
;;;  ~ 1111110
;;;     ^    ^

; end condition (c>>5) & 1 =>  0 = low
; start cond: c&1 => 0 = high
; (prev>>5)&1 == curr&1  means we have a discontinuity
; ((prev>>5) ^ curr) & 1 == 0  means we have a discontinuity

Test harness (modified from attinat's TIO link, beware the C sequence-point UB in that C reference function). Try it online!. This function is correct for all 30 cases. (Including the single-character cases where the return value doesn't match: both are truthy with different non-zero values in that case.)

# Excel, 79 bytes

Cell A1 as input

=1---SUMPRODUCT(--ISNUMBER(FIND({"//","/_","\~","\\","~/","~_","_\","_~"},A1)))

# naz, 142 bytes

2a2x1v4a8m1s2x2v2m2s2x3v3a2x4v3d4m2a2x5v1x1f1r3x2v2e3x3v3e3x4v3e2f0x1x2f1r3x1v4e3x3v3e3x5v2e0m1o0x1x3f1r3x1v4e3x2v2e3x4v3e0m1o0x1x4f0m1a1o0x1f

Another answer with a lot of conditionals - so many, in fact, that halfway through writing the explanation for a 206-byte solution, I realized an optimization I could make to achieve this one.

Works for any input string terminated with the control character STX (U+0002). ~ is expected instead of .

Explanation (with 0x commands removed)

2a2x1v                       # Set variable 1 equal to 2
4a8m1s2x2v                   # Set variable 2 equal to 47 ("/")
2m2s2x3v                     # Set variable 3 equal to 92 ("\")
3a2x4v                       # Set variable 4 equal to 95 ("_")
3d4m2a2x5v                   # Set variable 5 equal to 126 ("~")
1x1f                         # Function 1
1r                       # Read a byte of input
3x3v3e3x4v3e     # Jump to function 3 if it equals variable 3 or variable 4
1x2f                         # Function 2
1r                       # Read a byte of input
3x5v2e     # Jump back to the start of the function if it equals variable 5
0m1o # Otherwise, output 0
1x3f                         # Function 3
1r                       # Read a byte of input
3x4v3e     # Jump back to the start of the function if it equals variable 4
0m1o # Otherwise, output 0
1x4f0m1a1o                   # Function 4
# Output 1
1f                           # Call function 1

# Dart, 94 bytes

f(s)=>!(r'//,\\,~/,_\,~_,_~,/_,\~'.split(',').map((t)=>s.contains(t)).fold(false,(p,e)=>p|e));

Try it online!

## C++, 132 110 bytes

-22 bytes thanks to ASCII-only

int f(char*s){int t[128];t[95]=0;t[47]=1;t[92]=2;t[126]=3;for(;*++s;)if(t[s[-1]]%2^t[*s]/2)return 0;return 1;}

Uses a bitmask to know if the start and end are up or down

• hmm. wouldn't porting the C version be golfier :P Mar 19 '19 at 0:17
• 114 Mar 19 '19 at 0:19
• 110 Mar 19 '19 at 0:25

# Regex, 34 bytes

I couldn't find rules on using Regex as a language. Please let me know if I need to adjust this.

^(‾+|(‾*\\)?(_*\/‾*\\)*_*(\/‾*)?)\$

Try it here: https://regex101.com/r/s9kyPm/1/tests

• That's 34 bytes, not 24, right? Mar 19 '19 at 0:18
• Well, really 42 bytes, but you can change to ~
– Jo King
Mar 19 '19 at 5:29

# APL+WIN, 58 bytes

m←2 2⊤'_/\~'⍳s←,⎕⋄(1+⍴s)=+/((↑m[0;]),m[1;])=m[0;],¯1↑m[1;]

Prompts for input of string, index origin 0 and uses ~ for upper character

Try it online! Courtesy of Dyalog Classic