Drawing one-liner

15

1

CodeDrawing one-liner

Teaser

Behold this formidable drawing:

Can you draw this in a single stroke? Give it a try.

Can you do this one, now:

Give it a try.

How it works

These "make this drawing with one pen stroke" problems are problems with a rather simple solution. For each vertex, compute its degree. If all vertices have an even degree or if only two vertices have an odd degree, this is possible. In any other case, it is impossible. This is the same as finding an Eulerian path in the graph. This is also related to the very famous seven bridges of Königsberg puzzle.

For the first drawing, the degrees are

   2
 /   \
4-----4
|\   /|
|  4  |
|/   \|
3-----3

so we are in the second possible case, as all numbers are even except for the two 3s in the bottom. What is more, when we have odd numbers, we have to start in one of them and finish in the other. When everything is even, we can start wherever we want but we will finish where we started.

For the second drawing it is impossible, as there are too many odd degrees:

     2
   /   \
  5-----5
 /|\   /|\
2 |  4  | 2
 \|/   \|/
  5-----5
   \   /
     2

Task

Given the degrees of the edges as input, decide if a corresponding drawing could be done in a single pen stroke. Output Truthy if such a feat is possible and output Falsy otherwise.

Input

The degrees of the vertices in any sensible format, such as

  • an array of integers like [2,4,4,4,3,3] or [2,5,5,2,4,2,5,5,2]
  • separate arguments to a function, like f(2,4,4,4,3,3) or f(2,5,5,2,4,2,5,5,2)

Output

A Truthy value if all numbers are even or exactly two of them are odd, Falsy otherwise.

Test cases

Truthy

[2, 4, 4, 3, 3]
[2, 2]
[1, 2, 3, 4, 6, 8]
[2, 4, 2, 4, 2, 4, 2, 4]
[8, 6, 8, 2, 2, 3, 11]
[1, 3]
[8]

Falsy

[1, 2, 3, 4, 5, 6]
[2, 3]
[9]
[7, 2, 2, 2]
[4, 2, 7]
[3, 3, 3, 3]
[1, 2, 3, 1, 1]
[1, 1, 4, 1, 1]
[7, 7, 7, 7, 7, 7, 7, 7]

This is so shortest submission in bytes, wins! If you liked this challenge, consider upvoting it... And happy golfing!

RGS

Posted 2020-02-15T08:55:42.460

Reputation: 5 047

2Amazingly, none of your falsy test cases can really come from a graph! – Christian Sievers – 2020-02-15T09:54:17.563

@ChristianSievers included a couple of test cases from trees and the complete graphs on 4 and 8 vertices :) but I wasn't excluding the possibility of a graph having self-loops or multiple edges, so these could come from multi-graphs :) – RGS – 2020-02-15T10:01:30.710

3Even then the sum of the degrees should be twice the number of edges and therefore an even number – Christian Sievers – 2020-02-15T10:09:11.547

@ChristianSievers yes, and so what? :) – RGS – 2020-02-15T12:34:08.803

2Are you saying impossible lists of integers may be inputs? If so I think it should be clear in the spec (i.e. "The degrees of the vertices" would not be a correct description of the input). – Jonathan Allan – 2020-02-15T12:54:25.973

1As far as I know, these conditions are necessary but not sufficient i.e. one-strokyness implies them, but not the other way around – Varad Mahashabde – 2020-02-16T18:23:15.550

@VaradMahashabde the conditions are equivalent to the one-strokeyness, actually :) you can read about it by googling Eulerian path. The idea is that, as you traverse the edges, whenever you arrive at a vertex you must be able to leave it, thus requiring vertices to have even degree. This has one exception: if you don't arrive at the vertex from where you left, then those two vertices must have odd degree. Of course all of this is happening in a connected graph :) – RGS – 2020-02-16T19:23:08.567

1

Related puzzle https://codeforces.com/problemset/problem/788/B

– qwr – 2020-02-18T00:12:07.340

Answers

13

Python, 31 bytes

lambda l:sum(n%2for n in l)|2<3

Try it online!

We use k|2<3 to check that k is either 0 or 2. This works because the bit operation |2 sets the bit for place-value 2, so to get a result that's 2 or less, there must be no other bits set.

xnor

Posted 2020-02-15T08:55:42.460

Reputation: 115 687

A really good golf, as per usual! +1 – RGS – 2020-02-15T21:40:31.767

5

Wolfram Language (Mathematica), 25 bytes

(a=Tr@Mod[#,2])==0||a==2&

Try it online!

J42161217

Posted 2020-02-15T08:55:42.460

Reputation: 15 931

+1 on this really short submission! Tr is summing everything, right? – RGS – 2020-02-15T21:43:52.113

2@RGS If I recall correctly, Tr calculates the trace of a matrix, but for a vector that's simply the sum of the elements. – Neil – 2020-02-16T00:09:15.307

4

05AB1E, 5 4 bytes

Thanks to 05AB1E's weird boolification system, any number but 1 is falsy.

-1 Thanks to Jonathan Allan

ÉO1α

Try it online!

Explanation

É     Vectorizing n % 2
 O    Sum the resulting list
  1α  |n - 1|

a'_'

Posted 2020-02-15T08:55:42.460

Reputation: 1 099

Are you going to submit answers in all the languages you know..? XD – RGS – 2020-02-15T09:48:33.410

I believe any integer but 1 is falsey in 05AB1E, if so you don't need the Θ. – Jonathan Allan – 2020-02-15T13:22:01.443

This is incredibly short! Good job – RGS – 2020-02-15T21:45:10.973

3

Charcoal, 8 bytes

⁼¹↔⊖Σ﹪A²

Try it online! Link is to verbose version of code. Port of @ovs' 05AB1E answer. Explanation:

      A     Input array
     ﹪ ²    Vectorised modulo literal 2
    Σ       Sum
   ⊖        Decremented
  ↔         Absolute
⁼¹          Equals literal 1

There are other ways to check for 0 or 2 for the same byte count, such as Not(Decremented(Absolute(Decremented(...)))), Equals(2, BitwiseOr(2, ...)), or Count("02", Cast(...)) (careful not to use "20" of course).

Neil

Posted 2020-02-15T08:55:42.460

Reputation: 95 035

Thanks for your submission! +1 – RGS – 2020-02-15T21:40:55.840

3

Retina 0.8.2, 18 bytes

M`[13579]\b
^[02]$

Try it online! Link includes test cases. Explanation:

M`[13579]\b

Count the number of odd numbers.

^[02]$

Compare to 0 or 2.

Neil

Posted 2020-02-15T08:55:42.460

Reputation: 95 035

I don't think a Retina answer this short is legal. I'm calling the cops – RGS – 2020-02-15T21:45:36.693

I don't think calling the cops without any legitimate reason is legal. I'm stopping the cops – a'_' – 2020-02-16T15:14:38.730

3

Turing Machine But Way Worse, 1245 bytes

0 0 0 1 1 0 0
0 1 0 1 2 0 0
1 2 1 1 3 0 0
1 3 1 1 4 0 0
0 4 0 1 5 0 0
1 4 1 1 5 0 0
0 5 0 1 6 0 0
1 5 1 1 6 0 0
0 6 0 1 7 0 0
1 6 1 1 7 0 0
0 7 0 1 0 0 0
1 7 1 1 8 0 0
0 8 0 1 9 0 0
0 9 0 1 a 0 0
1 a 1 1 b 0 0
1 b 1 1 c 0 0
0 c 0 1 d 0 0
1 c 1 1 d 0 0
0 d 0 1 e 0 0
1 d 1 1 e 0 0
0 e 0 1 f 0 0
1 e 1 1 f 0 0
0 f 0 1 0 0 0
1 f 1 1 8 0 0
0 b 0 1 k 0 0
0 3 0 1 4 0 0
0 g 0 1 h 0 0
0 h 0 1 i 0 0
1 i 1 1 j 0 0
1 j 1 1 k 0 0
0 k 0 1 l 0 0
1 k 1 1 l 0 0
0 l 0 1 m 0 0
1 l 1 1 m 0 0
0 m 0 1 n 0 0
1 m 1 1 n 0 0
0 n 0 1 g 0 0
1 n 1 1 o 0 0
0 o 0 1 p 0 0
0 p 0 1 q 0 0
1 q 1 1 r 0 0
1 r 1 1 s 0 0
0 s 0 1 t 0 0
1 s 1 1 t 0 0
0 t 0 1 u 0 0
1 t 1 1 u 0 0
0 u 0 1 v 0 0
1 u 1 1 v 0 0
0 v 0 1 g 0 0
1 v 1 1 o 0 0
0 r 0 1 A 0 0
0 j 0 1 k 0 0
0 w 0 1 x 0 0
0 x 0 1 y 0 0
1 y 1 1 z 0 0
1 z 1 1 A 0 0
0 A 0 1 B 0 0
1 A 1 1 B 0 0
0 B 0 1 C 0 0
1 B 1 1 C 0 0
0 C 0 1 D 0 0
1 C 1 1 D 0 0
0 D 0 1 w 0 0
1 D 1 1 E 0 0
0 E 0 1 F 0 0
0 F 0 1 G 0 0
1 G 1 1 H 0 0
1 H 1 1 I 0 0
0 I 0 1 J 0 0
1 I 1 1 J 0 0
0 J 0 1 K 0 0
1 J 1 1 K 0 0
0 K 0 1 L 0 0
1 K 1 1 L 0 0
0 L 0 1 w 0 0
1 L 1 1 E 0 0
0 H 0 1 0 0 1
0 z 0 1 A 0 0
0 2 1 1 M 0 0
0 y 1 1 M 0 0
0 q 1 1 M 0 0
0 M 1 1 N 0 0
0 N 0 1 O 0 0
0 O 0 1 P 0 0
0 P 0 1 Q 0 0
0 Q 1 1 0 1 1
0 a 0 1 0 0 1
0 i 0 1 0 0 1
0 G 0 1 0 0 1

Try it online!

Input: A list like n, n, n, n, ...
Output: (blank) for falsy, 1 for truthy

u_ndefined

Posted 2020-02-15T08:55:42.460

Reputation: 1 253

1I take my hat off to you for your work :p +1 – RGS – 2020-02-17T13:52:28.367

2

05AB1E, 6 5 bytes

-1 byte thanks to a'_'.

ÉO<ÄΘ

Try it online!

Explanation

É       is the number odd (vectorizes over the input list)
 O      sum (number of odd values)
  <     decrement (number of odd values - 1)
   Ä    absolute value (|number of odd values - 1|)
    Θ   equal to 1 (|number of odd values - 1| == 1)

ovs

Posted 2020-02-15T08:55:42.460

Reputation: 21 408

5 bytes by using a == 1 built-in. I guess you win. – a'_' – 2020-02-15T10:28:44.883

@a'_' thanks a lot. It took me a while to understand this because lowercase and uppercase theta look much too similar. – ovs – 2020-02-15T10:39:55.467

@ovs let's ask Greece to change their alphabet a bit! +1 on your short submission – RGS – 2020-02-15T21:41:46.080

2

JavaScript (ES6), 29 bytes

a=>a.map(x=>m>>=x&1,m=5)&&m&1

Try it online!

How?

We start with the bitmask \$m=101_2=5_{10}\$ and right-shift it by one position for each odd value in the input array. The final result is given by the parity of \$m\$.

Arnauld

Posted 2020-02-15T08:55:42.460

Reputation: 111 334

Ah this feels really clever! +1 – RGS – 2020-02-15T21:47:28.900

2

Bash + Unix utilities, 28 bytes

dc<<<`grep -c [13579]$`d2-*p

Try it online!

Input is on stdin: one number per line.

Output is on stdout: 0 is truthy, any non-zero value is falsy.

How it works:

  • grep counts the number n of lines ending with an odd digit;
  • dc then computes and prints n*(n-2), which is 0 iff n equals 0 or 2.

Mitchell Spector

Posted 2020-02-15T08:55:42.460

Reputation: 3 392

2

C++ (gcc), 73 64 bytes

I don't know why I keep trying.

int f(int*a,int s){int o=1;for(;s;)o+=a[--s]%2;return o%2&&o<4;}

Commented :

int f(int*a,int s){ // function definition

  int o=1;      // odd counter starts at 1 because then parity of truthy inputs is one

  for(;s;)          // Use size arg as counter and iterate backwards (Thanks @MitchellSpector)
    o+=a[--s]%2;    // check for odd, add parity

  return o%2&&o<4;  // Valid values for odd are 0 and 2 (or rather 1 and 3)
                    // Solve with parity and range check
}

TIO-k6qqj7ln

Varad Mahashabde

Posted 2020-02-15T08:55:42.460

Reputation: 171

You keep trying because this is fun! +1 – RGS – 2020-02-16T23:55:34.970

Nice... Keeping the basic idea, here's how you can get it down from 73 to 64 bytes: int f(int*a,int s){int o=1;for(;s;)o+=a[--s]%2;return o%2&&o<4;} – Mitchell Spector – 2020-02-17T01:53:50.600

1@MitchellSpector My good coding practice of not editing the arguments is showing!! – Varad Mahashabde – 2020-02-17T17:20:29.197

2

Excel, 50 bytes

=ISNUMBER(FIND(SUMPRODUCT(--(MOD(A:A,2)=1)),"02"))

MOD(A:A,2)=1 to find odd number SUMPRODUCT() to count them FIND( ,"02") to check if 0 or 2 ISNUMBER() to converts to TRUE/FALSE

Feels very clunky, hope to refine...

Wernisch

Posted 2020-02-15T08:55:42.460

Reputation: 2 534

Looks nice :D +1 – RGS – 2020-02-17T17:42:30.913

1

Python 3, 34 bytes

lambda a:sum(n%2for n in a)in(0,2)

Try it online!

ovs

Posted 2020-02-15T08:55:42.460

Reputation: 21 408

Good job on this one! +1 – RGS – 2020-02-15T09:47:28.423

1

W d, 8 7 bytes

♦æ╥└¬y÷

Uncompressed:

2mJ1-z1=

Explanation

2m       % Modulo the list by 2, auto-vectorizes.
  J      % Sum the list.
   1-    % Decrement by 1.
     z   % Absolute value.
      1= % Is this 1?

a'_'

Posted 2020-02-15T08:55:42.460

Reputation: 1 099

When you look at this on mobile the first character is the moderator diamond. – S.S. Anne – 2020-02-16T01:08:09.703

Yes, but without the aeTLlyt. – S.S. Anne – 2020-02-16T15:19:32.217

1

Stax, 8 bytes

This method is shorter in Stax.

ƒ╟⌡≡ù₧╬)

Run and debug it

Explanation

{2%m       Map modulo 2 over the input
    |+     Sum the resulting list
      02\  In the list [0, 2]:
         # How many times does this number appear?

a'_'

Posted 2020-02-15T08:55:42.460

Reputation: 1 099

1

Keg, 13 bytes

÷⑷2%⑸⅀:0=$2=+

Try it online!

Simply using everyone else's algorithm!

Lyxal

Posted 2020-02-15T08:55:42.460

Reputation: 5 253

Why bother coming up with your own algorithm if everyone else is doing great, right? +1 – RGS – 2020-02-15T21:48:00.353

1@RGS Exactly! Who cares about originality anyway! :P – Lyxal – 2020-02-15T21:49:02.933

1

Japt -!, 7 bytes

èu a1 É

Try it

Shaggy

Posted 2020-02-15T08:55:42.460

Reputation: 24 623

Thanks for your submission! +1 were you the one designing the Japt interpreter? – RGS – 2020-02-15T21:46:07.833

Yes, @RGS, that interpreter is my creation. – Shaggy – 2020-02-16T00:41:14.763

it looks really good! I just wanted you to know that! Good job on that :) – RGS – 2020-02-16T10:56:28.947

1

PHP, 39 43 bytes

for(;$n=$argv[++$i];)$s+=$n%2;echo!($s&-3);

Try it online!

Guillermo Phillips

Posted 2020-02-15T08:55:42.460

Reputation: 561

Thanks misread the question! Fixed. – Guillermo Phillips – 2020-02-15T20:43:06.487

@Arnauld thanks for the help here :) – RGS – 2020-02-15T21:46:59.227

1

Perl 5 -pa, 20 bytes

$_=(2|grep$_%2,@F)<3

Try it online!

Borrows the |2<3 trick from @xnor's Python answer

Xcali

Posted 2020-02-15T08:55:42.460

Reputation: 7 671

Good job porting xnor's trick and getting an answer shorter than his :) – RGS – 2020-02-15T21:46:43.630

1

Japt -!, 6 bytes

èu &-3

Try it

èu &-3        Full program taking in array of degrees U
èu            Amount of odd numbers in array
   &          Bitwise AND
    -3        With -3; -3 has very bit set except of the second bit (1111...11101)
-!            Zero -> True, Other numbers -> False

Embodiment of Ignorance

Posted 2020-02-15T08:55:42.460

Reputation: 7 014

Thanks for the Japt submission! Can't you have several test cases in the Japt interpreter? – RGS – 2020-02-15T21:44:40.913

I understand, thanks for the explanation!! – RGS – 2020-02-15T21:51:36.947

1

GolfScript, 11 bytes

{2%+}*(2?(!

Try it online!

My first go at it, may shrink it a bit. I made it so 1 is true, 0 is false, but if you're okay with the other way around, I can do different things :)

Short explanation; Convert all the elements to mod 2 and sum them. The only valid answers would be 0 or 2. Now, subtract 1 and square them. 0 is -1 is 1. 2 is 1 is 1. 0 and 2 both give you 1. Lastly, subtract 1 and perform a not operation to make all non-0, non-2 values to a 0 and the 0-2s to a 1.

Kind of roundabout, and I'm sure I can cut two characters somewhere.

Mathgeek

Posted 2020-02-15T08:55:42.460

Reputation: 408

This looks nice! +1 thanks for your submission – RGS – 2020-02-16T23:55:04.383

1

APL (Dyalog Unicode), 10 bytesSBCS

0 2∊⍨1⊥2∘|

Try it online!

Because a challenge needs an APL answer.

How it works

0 2∊⍨1⊥2∘|
       2∘|  ⍝ Modulo 2
     1⊥     ⍝ Sum
0 2∊⍨       ⍝ Is member of [0 2]?

Bubbler

Posted 2020-02-15T08:55:42.460

Reputation: 16 616

Yes it does! +1 for that :) – RGS – 2020-02-17T08:03:06.543

1

Whitespace, 102 bytes

[S S S N
_Push_0][S N
S _Dupe_0][N
S S N
_Create_Label_LOOP][S N
S _Dupe][S N
S _Dupe][T  N
T   T   _Read_STDIN_as_integer][T   T   T   _Retrieve][S N
S _Dupe_input][N
T   T   S N
_If_neg_Jump_to_Label_DONE][S S S T S N
_Push_2][T  S T T   _Modulo][T  S S S _Add][N
S N
N
_Jump_to_Label_LOOP][N
S S S N
_Create_Label_DONE][S N
N
_Discard][S N
S _Dupe][N
T   S T N
_If_0_Jump_to_Label_TRUTHY][S S S T S N
_Push_2][T  S S T   _Subtract][N
T   S T N
_If_0_Jump_to_Label_TRUTHY][T   N
S T _Print_as_integer][N
N
N
_Exit_program][N
S S T   N
_Create_Label_TRUTHY][S S S T   N
_Push_1][T  N
S T _Print_as_integer]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.

Since Whitespace inputs one integer at a time, the input should contain a trailing -1 so it knows when to stop reading integers and the input is done.
Outputs 1/0 for truthy/falsey respectively.

Try it online (with raw spaces, tabs and new-lines only).

Explanation in pseudo-code:

Integer n = 0
Start LOOP:
  Integer i = STDIN as input
  If(i < 0):
    Jump to Label DONE
  n = n + (i modulo-2)
  Go to next iteration of LOOP

Label DONE:
  If(n == 0): Jump to Label TRUTHY
  If(n-2 == 0): Jump to Label TRUTHY
  Print 0 as integer to STDOUT
  Exit program

Label TRUTHY:
  Print 1 as integer to STDOUT

Kevin Cruijssen

Posted 2020-02-15T08:55:42.460

Reputation: 67 575

I was starting to fear this would never happen :( +1 for making me happy on a Monday morning! Quick question: when reading from stdin, is there a default way of knowing the input is over? – RGS – 2020-02-17T08:17:19.643

1@RGS Whitespace only has two ways to read STDIN input: read as integer and read as character. So no, there isn't a default way of knowing the input is over, unless trying to read a next character that isn't there anymore, after which the program stops with an error. I usually use a newline as indicator when a string input is being asked; -1 if only positive integers are being asked; etc. – Kevin Cruijssen – 2020-02-17T08:21:20.073

1thanks! I was asking because the other day I read your "make a whitespace interpreter" challenge and as I read through the specs, I couldn't figure out how we'd know the input is over when programming in whitespace. For some reason I just kept thinking that, much like brainfck "reads" a 0 when input is over, whitespace must have a similar mechanism :p but it really doesn't need to and it doesn't have :) – RGS – 2020-02-17T08:33:10.103

1

MathGolf, 6 bytes

¥Σ(±1=

Try it online.

Explanation:

¥       # Take modulo-2 on each integer of the (implicit) input-list
 Σ      # Sum those
  (     # Decrease it by 1
   ±    # Take the absolute value
    1=  # And check whether this is equal to 1
        # (after which the entire stack joined together is output implicitly)

Kevin Cruijssen

Posted 2020-02-15T08:55:42.460

Reputation: 67 575

Cool subtracting by one and then absolute value to check for 0 and 2 – RGS – 2020-02-17T08:33:55.520

1

Java 8, 28 bytes

s->(s.map(i->i%2).sum()|2)<3

Port of @xnor's Python answer

Try it online.

Explanation:

s->               // Method with IntStream parameter and boolean return-type
  (s.map(i->i%2)  //  Take modulo-2 for each value in the IntStream
    .sum()        //  And them sum those
    |2)           //  Take a bitwise-OR with 2
       <3         //  And check whether that is smaller than 3

Kevin Cruijssen

Posted 2020-02-15T08:55:42.460

Reputation: 67 575

Keep up the good work +1 – RGS – 2020-02-17T10:52:27.017

1

C# (Visual C# Interactive Compiler), 26 bytes

p=>(p.Count(n=>n%2>0)|2)<3

Try it online!

Thanks to answer of @xnor -1B

27 bytes

p=>(p.Count(n=>n%2>0)&-3)<1

Try it online!

This one was my first attempt, but I made mistake at first so I'm publishing it now when I fixed it.

Jirka Picek

Posted 2020-02-15T08:55:42.460

Reputation: 171

Also a port of the python answer, right? +1 – RGS – 2020-02-17T13:53:53.770

1At first I made it by myself, but I made mistake when checking if the count is 0 or 2 so it didn't work as i expected so I got inspired by the |2<3 part. But I found the mistake now, so I will add my original thought (one byte longer) – Jirka Picek – 2020-02-20T07:29:10.697

really nice answers! Thanks for sharing – RGS – 2020-02-20T09:37:18.543

1

Chevron, 172 147 bytes

^__>^n
>^n>^t
^t~s>>^s
0>>^o
0>>^i
^i+1>>^i
^t,^i~c>>^c
->+2??^c~^_i
->-3
^n^c>^n
^n~o>>^z
^o+^z>>^o
^__>^n
->+2?^i=^s
->-9
^o-2>>^p
^o*^p>>^o
>^o

Takes numbers from stdin in the form 2 4 4 3 3.

Outputs 0 or -0 for truthy, anything else falsy.

Superloach

Posted 2020-02-15T08:55:42.460

Reputation: 71

Hey there, thanks for your submission! Could you please consider adding a tio link with the test cases?

– RGS – 2020-02-17T17:47:16.947

1Chevron isn't on tio yet, I'll work on that :) – Superloach – 2020-02-17T17:48:57.860

@RGS it's not tio, but here's something to test on :) https://ch.superloach.xyz/

– Superloach – 2020-02-17T19:39:20.110