Is it an exercise set?

16

1

We all know that a lot of exercises only affect one half of your body, so you have to do them twice, once for each side. Such exercises have two counterparts, one for the left side and one for the right. However, there's no need to execute the two counterparts consecutively, as long as the exercises for both sides are in the same order. You may as well switch between sides in your exercise program, but it wouldn't make sense to start some exercises with one side and some with the other.

Challenge

An exercise part is a list of non-zero integers, where its second half consists of the integers of the first half negated and in the same order, and the signs of the integers on each half are equal. The sign of the first half of an exercise part is its leading side.

An exercise set is zero or more exercise parts with the same leading side concatenated together.

Given a list of non-zero integers as input, determine if it is an exercise set. The integers aren't necessarily unique. The list's length isn't necessarily even.

Your solution may not use any of the standard loopholes. You may use any two different consistent values for output. This is , so the shortest solution wins.

Examples

[-5, -1, -7, -6, -5, 5, 1, 7, 6, 5] is an example of an exercise part. The first half is [-5, -1, -7, -6, -5], and the last half is [5, 1, 7, 6, 5], which is each integer in the first half negated. Additionally, the first half's integers are all of the same sign. This exercise part's leading side is -1.

[3, 6, 5, -3, -6, -5, 1, 6, 4, 3, -1, -6, -4, -3] is an example of an exercise set. Its individual exercise parts are [3, 6, 5, -3, -6, -5] and [1, 6, 4, 3, -1, -6, -4, -3], and they both have leading side 1.

[4, -4, -5, 5], despite only consisting of valid exercise parts, isn't an exercise set, since the first part, [4, -4], has leading side 1, while the second part, [-5, 5], has leading side -1.

Test cases

Valid test cases:

[]
[1, -1]
[1, -1, 1, -1]
[-6, 6, -5, -4, -3, 5, 4, 3]
[-1, -5, -8, 1, 5, 8, -7, -6, -5, -3, 7, 6, 5, 3]
[-1, -5, -8, 1, 5, 8, -1, 1]

Invalid test cases:

[1]
[1, -2]
[1, 2, -3, -1, -2, 3]
[1, 2, 3, -3, -1, -2]
[-1, -5, -8, 1, 5, 8, 7, 6, 5, 3, -7, -6, -5, -3]
[1, 2, 3, 5, 1, 2, 3, 5]
[1, 2, -5, 4, -6, 5, 5, -6]
[1, 2, -1, 3, -2, -3]
[1, -2, 1]
[-1, -1, 1]
[1, -1, 1]

Erik the Outgolfer

Posted 2018-05-24T12:37:28.073

Reputation: 38 134

3The empty case is an annoyance. And to interpret the words of the challenge I'm not sure if there is a valid way to assign "not exercising at all" to either one side or the other of "is it an exercise set?" But to be honest I'm just whining. – ngm – 2018-05-24T13:55:41.810

@ngm Was just about to comment this.. Empty list is an annoying edge case.. Personally I would state the input contains at least one item. Apart from that nice challenge, though! – Kevin Cruijssen – 2018-05-24T13:57:07.323

1@ngm It's truthy by terms of vacuous truth. Consider it to be proper relaxation. ;) – Erik the Outgolfer – 2018-05-24T14:03:36.870

2It's nice to know I can golf and exercise at the same time. – ngm – 2018-05-24T14:06:17.793

@ngm "It's nice to know I can golf and exercise at the same time." We got more of those kind of challenges. ;)

– Kevin Cruijssen – 2018-05-24T14:11:48.373

This is hard AF in 05AB1E. – Magic Octopus Urn – 2018-05-24T21:39:45.307

Answers

5

Python 2, 69 67 bytes

a,b=x=[[],[]];k=0
for n in input():x[n>0]+=n*n,n*k>0;k=n
print a==b

Try it online!

Dennis

Posted 2018-05-24T12:37:28.073

Reputation: 196 637

4

Jelly, 10 bytes

ṁṠŒg$+2/FẸ

Try it online!

Dennis

Posted 2018-05-24T12:37:28.073

Reputation: 196 637

3

JavaScript (ES6), 54 bytes

Optimized version, inspired by Dennis' Python answer.

Returns 0 or 1.

a=>a.map(b=p=x=>b[+(x<0)]+=[x*x,p*(p=x)>0])|b[1]==b[0]

Try it online!


Original version, 74 bytes

a=>a.map(x=>b[i^=p*(p=x)<0&&-~(b[i]+=0)]+=[,x*x],b=[p=0,i=0])|b[1]+0==b[0]

Try it online!

How?

We store the first halves of all exercise parts in b[0] and the second halves in b[1], switching between b[0] and b[1] each time the sign is changing. Entries are squared to get rid of the sign. We prefix each entry with a comma and suffix each part with a 0.

There's some extra logic to handle the 'empty input' edge case at basically no cost (see the comment near the end of the source code).

a =>                    // given the input array a[]
  a.map(x =>            // for each x in a[]:
    b[i ^=              //   access b[i]:
      p * (p = x)       //     we keep track of the previous entry in p
      < 0 &&            //     if p and x have opposite signs:
      -~(b[i] += 0)     //       append a '0' to b[i] and update i: 0 -> 1, 1 -> 0
    ] += [, x * x],     //   append a comma followed by x² to b[i]
    b = [p = 0, i = 0]  //   start with p = 0, i = 0 and b = [0, 0]
  ) |                   // end of map()
  b[1] + 0              // this will append a '0' to b[1] if it was turned into a string
                        // or let it unchanged if it's still equal to zero (integer),
                        // which handles the 'empty input' edge case
  == b[0]               // compare the result with b[0]

Arnauld

Posted 2018-05-24T12:37:28.073

Reputation: 111 334

3

R, 91 bytes

Inputs a whitespace-separated vector of numbers. Outputs FALSE for valid and TRUE for invalid.

x=scan()
y=x<0
z=rle(y)
"if"(sum(x|1),any(x[y]+x[!y],z$v==rev(z$v),z$l[!0:1]-z$l[!1:0]),F)

rle gives the run length encoding, in this case of the sequence of positive and negative values.

The completely and totally unfair empty edge case ;) adds a whopping 15 bytes.

Many bytes shaved off by @Giuseppe.

Here is a 92 byte version expressed as a function which is better for testing:

Try it online!

ngm

Posted 2018-05-24T12:37:28.073

Reputation: 3 974

3

Java 8, 186 183 185 bytes

a->{int i=a.length-1,t,j;boolean r=i%2>0,f;if(i<0)return!r;for(f=a[i]<0;i>0;){for(r&=f==(t=a[j=i])<0;j>0&&t>>>31==a[--j]>>>31;);for(t=i-j,i-=2*t;j>=0&j>i;)r&=a[j+t]==-a[j--];}return r;}

+2 bytes due to a bug-fix for test cases of size 3 (almost all permutations of 1 and -1 at the end of my TIO-link).

Can definitely be golfed.. The challenge looks to-the-point, but it's pretty hard to implement. Especially the test case [4,-4,-5,5] was annoying to fix.. But it works now. Will golf it down from here.

Try it online.

Explanation:

a->{                   // Method with integer-array parameter and boolean return-type
  int i=a.length-1,j,  //  Index integers (`i` starting at the last index)
      t;               //  Temp integer
  boolean r=i%2>0,     //  Result-boolean, starting at true if the input-list is even
          f;           //  Flag-integer
  if(i<0)              //  If the input was empty (edge case)
    return!r;          //   Return true
  for(f=a[i]<0;        //  Set the flag-boolean to "Is the current item negative?"
      i>0;){           //  Loop down over the array
    for(r&=f==(t=a[j=i])<0;
                       //   Set `s` to the current number
                       //   And verify if the initial flag and `s` have the same sign
        j>0            //   Loop `j` from `i` down as long as `j` is larger than 0,
        &&t>>>31==a[--j]>>>31;);
                       //   and both `s` and the current item have the same sign
                       //    Decreasing `j` by 1 every iteration
    for(t=i-j,         //   Set `t` to `i-j` (amount of same signed adjacent values)
        i-=2*t;        //   Decrease `i` by two times `t`
        j>=0           //   Loop as long as `j` is larger than or equal to 0,
        &j>i;)         //   and also larger than `i`
      r&=a[j+t]==-a[j--];}
                       //    Verify if the pairs at index `j+t` and `j`
                       //    are negatives of each other
  return r;}           //  Return if `r` is still true (if all verifications succeeded)

Kevin Cruijssen

Posted 2018-05-24T12:37:28.073

Reputation: 67 575

2

Python 2, 147 130 113 112 106 bytes

from itertools import*
def f(s):l=[map(abs,g)for v,g in groupby(s+[0],0 .__cmp__)];print l[1::2]==l[:-1:2]

Try it online!


Saved:

  • -27 bytes, thanks to Dennis

TFeld

Posted 2018-05-24T12:37:28.073

Reputation: 19 246

2lambda n:cmp(n,0) can become 0 .__cmp__. all(a==b for a,b in zip(l[::2],l[1::2])) can become l[:-1:2]==l[1::2]. – Dennis – 2018-05-24T14:42:32.403

2

Retina 0.8.2, 57 bytes

^\b|,\b
$&=
(.)(\d+),(?=\1)
$2_
-|=

.$
$&,
^((\w+,)\2)*$

Try it online! Takes comma-separated input, but link includes header that processes test cases. Explanation:

^\b|,\b
$&=

Insert a marker before each positive integer.

(.)(\d+),(?=\1)
$2_

Change the commas between integers of the same sign to underscores.

-|=

Delete the remaining signs.

.$
$&,

Append a comma if the input is not empty.

^((\w+,)\2)*$

Check that the string consists of pairs of runs of the same integers.

Neil

Posted 2018-05-24T12:37:28.073

Reputation: 95 035

1

Python 2, 111 bytes

x=input()
o=[];p=[]
for a,b in zip(x,x[1:]):
 if 0<a*x[0]:
	p+=a,-a
	if b*a<0:o+=p[::2]+p[1::2];p=[]
print o==x

Try it online!

Rod

Posted 2018-05-24T12:37:28.073

Reputation: 17 588

1

JavaScript (Node.js), 155 bytes

b=>eval('i=b.length-1;r=i%2;0>i&&!r;for(f=0>b[i];0<i;){for(r&=f==(s=0>b[j=i]);0<j&&s&0>b[--j]|!s&0<b[j];);t=i-j;for(i-=2*t;0<=j&j>i;)r&=b[j+t]==-b[j--]}r')

Try it online!


Inspiration was @KevinCruijssen's answer

Also thanks to him for correcting 2 test cases of mine

Muhammad Salman

Posted 2018-05-24T12:37:28.073

Reputation: 2 361

Since yours is inspired from my Java answer, you should change r=0<i to r=i%2, since the test cases [1,-1,1] and [-1,1,-1] are failing at the moment. Byte-count remains the same for JS, though. – Kevin Cruijssen – 2018-05-24T15:49:00.907

@KevinCruijssen : Thanks, done – Muhammad Salman – 2018-05-24T15:55:46.173

1

Stax, 13 bytes

Ç¥├W╦╣∩T~≥▌╨c

Run and debug it

recursive

Posted 2018-05-24T12:37:28.073

Reputation: 8 616

1

Brachylog, 18 14 bytes

~c{ḍz{ṅᵈ¹ṡ}ᵛ}ᵛ

Try it online!

Saved 4 bytes thanks to @ErikTheOutgolfer.

Explanation

                    Succeed if and only if:
~c                  You can deconcatenate the input list…
  {         }ᵛ      …and verify that for each of the sublists:
   ḍ                  Split it in half
    z                 Zip the elements of each half together
     {    }ᵛ          Verify that for each couple:
      ṅᵈ¹               The first integer is the negation of the second one
         ṡ              Take the sign of the first one
                      All signs should be equal in a sublist
                    All leading signs of the sublists should be equal

Fatalize

Posted 2018-05-24T12:37:28.073

Reputation: 32 976

0

APL (Dyalog Classic), 48 bytes

{0::1⋄0≠+/ר⍵:0⋄(~0∊⊢∨2|⍳∘⍴)2{⍺≡-⍵}/⍵⊂⍨1,2≠/ר⍵}

Try it online!

Zacharý

Posted 2018-05-24T12:37:28.073

Reputation: 5 710