14
\$\begingroup\$

A simple pedometer can be modeled by a pendulum with two switches on opposite sides—one at x=0 and one at x=l. When the pendulum contacts the far switch, the ambulator can be assumed to have taken half a step. When it contacts the near switch, the step is completed.

Given a list of integers representing positions of the pendulum, determine the number of full steps recorded on the pedometer.

Input

  • An integer l>0, the length of the track.

  • A list of integers representing the positions of the pedometer's pendulum at each time.

Output

The number of full steps measured. A step is taken when the pendulum contacts the far switch (x>=l) and then the near switch (x<=0).

Test cases

8, [8, 3, 0, 1, 0, 2, 2, 9, 4, 7]
1

The pendulum immediately makes contact with the far switch at x=8 at t=0. Then it touches the near switch at t=2 and t=4, completing one step. After that, it touches the far switch again at x=9 at t=8, but it never touches the near switch again.

1, [1, 5, -1, -4, -1, 1, -2, 8, 0, -4]
3

15, [10, -7, -13, 19, 0, 22, 8, 9, -6, 21, -14, 12, -5, -12, 5, -3, 5, -15, 0, 2, 11, -11, 12, 5, 16, 14, 27, -5, 13, 0, -7, -2, 11, -8, 27, 15, -10, -10, 4, 21, 29, 21, 2, 5, -7, 15, -7, -14, 13, 27]
7

7, [5, 4, 0]
0

7, [5, 8, 6, 1, 2] 
0   
\$\endgroup\$
4
  • 1
    \$\begingroup\$ What about 7, [5, 4, 0]? Is that 0 or 1? That is - do you assume that a swing is always "full-length"? Or 7, [5, 8, 6, 1, 2]? Is that 0 or 1? \$\endgroup\$ Commented Mar 8, 2016 at 20:31
  • 1
    \$\begingroup\$ @NotthatCharles Added. \$\endgroup\$
    – lirtosiast
    Commented Mar 8, 2016 at 20:34
  • \$\begingroup\$ I assume a step always is: contact at far end, then near end. That is: near end, then far end is not a full step. So input 8, [0 8 0 8] should give 1, not 2. Am I correct? \$\endgroup\$
    – Luis Mendo
    Commented Mar 8, 2016 at 23:55
  • \$\begingroup\$ @DonMuesli Yes. \$\endgroup\$
    – lirtosiast
    Commented Mar 9, 2016 at 0:31

10 Answers 10

4
\$\begingroup\$

CJam, 27 24 bytes

l~:Xfe<0fe>_[XT]:Y--Y/,(

Input format is the list of pendulum positions followed by l on a single line.

Test it here.

Explanation

l~     e# Read and evaluate input.
:X     e# Store track length in X.
fe<    e# Clamp each position to X from above.
0f>    e# Clamp each position to 0 from below.
_      e# Duplicate.
[XT]   e# Push the array [X 0].
:Y     e# Store it in Y.
-      e# Set subtraction from the clamped input list. This gives all the
       e# intermediate values.
-      e# Another set subtraction. Remove intermediate values from input list.
Y/     e# Split remaining list around occurrences of ...X 0...
,(     e# Count them and decrement. This is the number of times the pendulum
       e# moved from X to 0.
\$\endgroup\$
2
\$\begingroup\$

MATL, 22 bytes

>~2G0>~-XzY'nw1)0<-H/k

This uses current version (14.0.0) of the language/compiler.

Inputs are in the same order and format as in the challenge, separated by a newline.

Try it online!

Explanation

>~     % take the two inputs implicitly. Generate an array that contains true 
       % where the second input (array of positions) is >= the first input (l)
2G     % push second input (positions) again
0      % push a 0
>~     % true where the second input (array of positions) is <= 0
-      % subtract: array of 1, -1 or 0
Xz     % discard the 0 values
Y'     % run-length encoding: push values and number of repetitions
n      % length of the latter array: number of half-steps, perhaps plus 1
w1)    % swap. Get first element
0<     % true if that element is -1. We need to discard one half-step then
-      % subtract
H/k    % divide by 2 and round down
\$\endgroup\$
1
\$\begingroup\$

Javascript ES6 57 bytes

(t,a)=>a.map(a=>a<t?a>0?'':0:1).join``.split`10`.length-1

Thanks @NotThatCharles for -4

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Why not split on /10/? \$\endgroup\$ Commented Mar 8, 2016 at 21:29
  • \$\begingroup\$ @NotthatCharles I was so sure that didn't work, just tried it and it's great! - thanks \$\endgroup\$ Commented Mar 8, 2016 at 21:33
  • 4
    \$\begingroup\$ One Charles to another ;) \$\endgroup\$ Commented Mar 8, 2016 at 21:34
1
\$\begingroup\$

Perl, 28 bytes

Includes +1 for -p

Run with the input as one long line of space separated integers on STDIN, the first number is the length:

perl -p steps.pl <<< "8 8 3 0 1 0 2 2 9 4 7"

steps.pl:

s; ;$'>=$_..$'<1;eg;$_=y;E;

Uses the perl flip-flop operator and counts the number of times it returns to false

\$\endgroup\$
1
\$\begingroup\$

Pyth, 18 bytes

/.:@J,Q0m@S+Jd1E2J

Test suite

Explanation:

/.:@J,Q0m@S+Jd1E2J
                      Implicit: Q is the length of the track.
    J,Q0              Set J to [Q, 0]
        m      E      Map over the list
           +Jd        Add the current element to J
          S           Sort
         @    1       Take the middle element.
                      This is the current element, 
                      clamped above by Q and below by 0.
   @J                 Filter for presence in J.
 .:             2     Form 2 element substrings
/                J    Count occurrences of J.
\$\endgroup\$
0
\$\begingroup\$

Ruby, 42

->i,a{r=!0
a.count{|v|r^r=v>=i||r&&v>0}/2}

r starts as false. We toggle r at each end of the track, and add it to our count. Then, halve the count (rounding down) to get the number of steps.

\$\endgroup\$
0
\$\begingroup\$

Retina, 34

-1*

^(1*)((?>.*?\1.*? \D))*.*
$#2

Try it online! or try it with decimal input.

Takes input in unary, negative unary numbers are treated as -111... and zero is the empty string. Counts the number of times that the first number appears followed by a zero. Uses an atomic group to guarantee that the matches are minimal (sadly atomic groups are non-capturing so it has to be wrapped in another group...).

\$\endgroup\$
0
\$\begingroup\$

Python 3, 82

Saved 2 bytes thanks to DSM.

Not super golfed yet.

def f(x,s):
 c=l=0
 for a in s:
  if a>=x:l=x
  elif a<1:c+=l==x;l*=l!=x
 return c

Test cases:

assert f(8, [8, 3, 0, 1, 0, 2, 2, 9, 4, 7]) == 1
assert f(1, [1, 5, -1, -4, -1, 1, -2, 8, 0, -4]) == 3
assert f(15, [10, -7, -13, 19, 0, 22, 8, 9, -6, 21, -14, 12, -5, -12, 5, -3, 5, -15, 0, 2, 11, -11, 12, 5, 16, 14, 27, -5, 13, 0, -7, -2, 11, -8, 27, 15, -10, -10, 4, 21, 29, 21, 2, 5, -7, 15, -7, -14, 13, 27]) == 7
\$\endgroup\$
0
\$\begingroup\$

Clojure, 64 bytes

#(count(re-seq #"10"(apply str(for[i %2](condp > i 1 0 %""1)))))

Maps values less-than-or-equal of zero to 0, larger-than-or-equal of length to 1 and others to an empty string "". This is then concatenated to a string and occurrences of "10" are counted.

\$\endgroup\$
0
\$\begingroup\$

APL (Dyalog Unicode), 17 bytesSBCS

Also known as "how much can I abuse iota-underbar?"

≢∘∪0~⍨(⍸≤)⍸(⍸0≥⊢)

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.