21
\$\begingroup\$

Introduction

You're making a robot that can navigate a set of books of varying heights. It can climb books and jump off books, but if the distance is too big it will stop to prevent damage. To figure out the ideal design, you're writing a simulator.

Your program will take as input a list of numbers, representing the heights of the books in the bookshelf, as well as a number indicating the durability of the robot. Starting from the first item of the list, your robot will traverse the bookshelf. If the robot comes across a change in height, it will only be able to continue if the change is less than or equal to the robot's durability. Your job is to output which book the robot is on when it stops, starting from either 0 or 1. You may safely assume that the height of the first book the robot is on will be equal to or less than the robot's durability.

Scoring

This is code-golf, so shortest answer wins.

Examples (starting from 1)

[1, 1, 1], 1 -> 3
[0, 1, 0], 0 -> 1
[1, 2, 3, 2], 1 -> 4
[1, 3, 4, 4, 0], 2 -> 4
[1, 3, 4, 4, 0, 1], 2 -> 4
\$\endgroup\$
6
  • 1
    \$\begingroup\$ @solid.py Good point. I've clarified the examples. \$\endgroup\$
    – Ginger
    Jan 31, 2022 at 18:57
  • 5
    \$\begingroup\$ Suggest test case [1, 3, 4, 4, 0, 1], 2 -> 4. Currently, an algorithm that simply counts the number of elements less than or equal to durability in the absolute differences of heights returns the correct output for all test cases, but it will fail on this one. \$\endgroup\$
    – chunes
    Jan 31, 2022 at 19:24
  • \$\begingroup\$ And that statement is sort of a non-sequitur anyway, since we don't care about the absolute height of the books, only the relative heights. \$\endgroup\$
    – Sundar R
    Feb 1, 2022 at 23:37
  • \$\begingroup\$ @chunes Does this start from 0 or 1? \$\endgroup\$
    – Ginger
    Feb 2, 2022 at 12:40
  • \$\begingroup\$ @Lynn Sorry, fixed. \$\endgroup\$
    – Ginger
    Feb 2, 2022 at 12:41

25 Answers 25

11
\$\begingroup\$

Wolfram Language (Mathematica), 33 bytes

dIf[Abs[#2-#]>d,0,1+#0@##2,0]&

Try it online!

Input [durability][heights...]. Returns 0-indexed.

If[Abs[#2-#]>d             ]    is the next height difference out of limits?
              ,0                  yes: 0
                ,1+#0@##2         no : recurse on tail and add 1
                         ,0       err: 0 (input len <2)
\$\endgroup\$
7
\$\begingroup\$

Octave / MATLAB, 37 35 bytes

2 bytes saved thanks to @Giuseppe!

@(x,d)sum(cumprod(abs(diff(x))<=d))

Output is 0-based.

Try it online!

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

Vyxal, 7 bytes

¯ȧ<1JTh

Try it Online!

¯ȧ      # Get absolute differences
  <     # Find all less than the input
   1J   # Append a 1
      h # Get the first...
     T  # Index of a 1
\$\endgroup\$
6
\$\begingroup\$

JavaScript (ES7), 41 bytes

-6 thanks to @emanresu A

d=>f=([a,...x])=>(a-x[0])**2<=d*d&&-~f(x)

JavaScript (ES7), 42 bytes

d=>f=([a,...x])=>(a-x[0])**2<=d*d?f(x)+1:1

Recursive solution. Takes input via currying, robot durability first.

Relies on NaN <= x always being false, saving a check to see if x is long enough.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ @emanresuA Nope, due to the NaN trick that causes infinite recursion if the robot wouldn't break \$\endgroup\$ Jan 31, 2022 at 18:13
6
\$\begingroup\$

Emojicode, 272 bytes

🏁🍇💯🆕🔡👂🏼❗️❗️➡️d🎶🆕🔡👂🏼❗️❗️➡️l l➡️🖍🆕a 0➡️🖍🆕c🐨a 0❗️🔂v a🍇↪️🍺💯v❗️➖🍺💯🐽l c❗️❗️▶🙌🍺d🍇🚪🐇💻c❗️🍉c⬅️➕1🍉🚪🐇💻c❗️🍉

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ I still don't understand what compelled me to do this. \$\endgroup\$
    – Ginger
    Mar 19, 2022 at 15:03
6
\$\begingroup\$

Perl 5 + -pa, 40 bytes

//,$\++while!eof&&"@F">=abs+($_=<>)-$'}{

Try it online!

Explanation

Thanks to -pa the durability is stored in $_ (although this is quickly overwritten) and @F. This then loops while STDIN is not eof and "@F" (interpolates the values in @F, just the durability in this case) is greater than the next input (retrieved with <> and stored in $_) subtracted from the remainder of the previous m//atch (which starts out empty, 0 in numeric context). The body of the while is matching against nothing, purely to store the previous value in $' without having to set manually, and incrementing $\, which is automatically output thanks to -p. The final }{ is to break out of the implicit while (<STDIN>) from -p (well, -n which is implied by -p) to prevent $_ being output as well.

\$\endgroup\$
5
\$\begingroup\$

Python 3, 80 bytes

Returns 0-based index.

lambda l,n:next((i for i,(a,b)in enumerate(zip(l,l[1:]))if abs(a-b)>n),len(l)-1)

Try it online!

\$\endgroup\$
5
\$\begingroup\$

Jelly, 7 bytes

5 if we may output 1-indexed and modular (i.e. yield 0 for the rightmost) - remove ;1

IA>;1TḢ

A dyadic Link accepting a list and an integer that yields the 1-indexed stopping point.

Try it online!

How???

IA>;1TḢ - Link: list, B; integer, D
I       - incremental differences of B
 A      - absolute values
  >     - greater than D?
   ;1   - concatenate a one
     T  - truthy 1-indexed indices
      Ḣ - head
\$\endgroup\$
2
  • \$\begingroup\$ Hm, exactly the same as my Vyxal. \$\endgroup\$
    – emanresu A
    Feb 1, 2022 at 5:47
  • 1
    \$\begingroup\$ I suppose ạƝ rather than IA would make it exactly the same, but yep! \$\endgroup\$ Feb 1, 2022 at 12:04
5
\$\begingroup\$

Haskell, 42 bytes

(a:b:r)!s|s<abs(a-b)=1
(h:t)!s=1+t!s
x!_=0

Try it online!

Three definitions of infix !

  • 1st: guards against big step stopping the robot.
  • 2nd: step was fine, continue.
  • 3rd: end of list.
    Due to 1 indexing it was possible to save something by reaching end of list instead of ending at a single element e.g. [x]!_=0
\$\endgroup\$
5
\$\begingroup\$

Factor, 50 43 bytes

[ differences vabs [ >= ] with count-head ]

count-head postdates build 1525, the one TIO uses, so here's a screenshot running this in Factor's REPL:

enter image description here

Explanation

Takes input as durability heights. 0-indexed. count-head is a combinator that applies a quotation to each element of a sequence, counting how many times the quotation returns t and stopping once an f is encountered.

                        ! 2 { 1 3 4 4 0 }
differences             ! 2 { 2 1 0 -4 }
vabs                    ! 2 { 2 1 0 4 }
[ >= ] with count-head  ! 3
\$\endgroup\$
5
\$\begingroup\$

05AB1E, 7 bytes

¥Ä‹1ª1k

0-based.

Try it online or verify all test cases.

Explanation:

¥        # Get the deltas/forward-differences of the first (implicit) input-list
 Ä       # Convert each to its absolute value
  ‹      # Check for each integer in the list whether the second (implicit)
         # input-integer is smaller than it
   1ª    # Append a trailing 1
     1k  # Pop the list, and push the (0-based) index of the first 1
         # (which is output implicitly as result)

Could be 5 bytes if we're allowed to output a modular index, so it'll output -1 if it's able to travel across all books:

¥ÄÅΔ‹

Try it online or verify all test cases.

Explanation:

¥Ä     # Same as above
  ÅΔ   # Push the first 0-based index which is truthy for
       # (or -1 if none were truthy)
    ‹  #  Check if the second (implicit) input-integer is smaller than the
       #  current integer
       # (after which the found index is output implicitly as result)
\$\endgroup\$
5
\$\begingroup\$

C (gcc), 56 51 49 bytes

f(a,n,d)int*a;{n=!--n||(*a-*++a)/~d?:1+f(a,n,d);}

Try it online!

Saved 5 bytes thanks to att!!!
Saved 2 bytes thanks to AZTECCO!!!

Inputs a pointer to an array of integers, its length (because pointers in C carry no length info), and the durability of the robot.
Returns to the number of the book (starting at \$1\$) that the robot stops at.

\$\endgroup\$
4
  • \$\begingroup\$ 51 bytes \$\endgroup\$
    – att
    Feb 1, 2022 at 0:08
  • \$\begingroup\$ @att Very nice - thanks! :D \$\endgroup\$
    – Noodle9
    Feb 1, 2022 at 10:37
  • 1
    \$\begingroup\$ 49 \$\endgroup\$
    – AZTECCO
    Feb 1, 2022 at 13:34
  • \$\begingroup\$ @AZTECCO Clever way around abs - thanks! :D \$\endgroup\$
    – Noodle9
    Feb 1, 2022 at 14:40
5
\$\begingroup\$

Python 3, 53 bytes

s=lambda d,f,*t,p=0:d<abs(f-p)or t==()or-~s(d,*t,p=f)

Try it online!

Input is taken as varargs. Surprisingly the 1-based indexing makes the code shorter, since "or" is a byte shorter than "and".

\$\endgroup\$
5
\$\begingroup\$

Japt, 10 bytes

I am ridiculously out of practice! 0-indexed.

äa pVÄ b>V

Try it

\$\endgroup\$
4
\$\begingroup\$

Wolfram Language (Mathematica), 40 bytes

Output is 0-base

LengthWhile[Abs@Differences@#-#2,#<=0&]&

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Charcoal, 20 bytes

I⌕Eθ∨⁼κ⊖Lθ‹η↔⁻ι§θ⊕κ¹

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

   θ                    Input list
  E                     Map over values
      κ                 Current index
     ⁼                  Equals
         θ              Input list
        L               Length
       ⊖                Decremented
    ∨                   Logical Or
           η            Input durability
          ‹             Is less than
              ι         Current value
            ↔⁻          Absolute difference with
                θ       Input list
               §        Indexed by
                  κ     Current index
                 ⊕      Incremented
 ⌕                      Find index of
                   ¹    Literal integer `1`
I                       Cast to string
                        Implicitly print
\$\endgroup\$
4
\$\begingroup\$

K (ngn/k), 21 bytes

{*&(y<x|-x:1_-':x),1}

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Julia 1.0, 37 bytes

h/r=findfirst(abs.(diff([h;Inf])).>r)

Try it online!

35 bytes porting @LuisMendo's Octave solution: h/r=sum(cumprod(abs.(diff(h)).<=r))

\$\endgroup\$
3
\$\begingroup\$

Python 3, 71 bytes

lambda h,d:([abs(h[i+1]-h[i])>d for i in range(len(h)-1)]+[1]).index(1)

Try it online!

\$\endgroup\$
4
3
\$\begingroup\$

APL+WIN, 12 14 bytes

Plus 2 bytes to accomodate new example suggested by @chunes

Prompts for heights then durability. Index = 1

+/^\1,⎕≥|-2-/⎕

Try it online! Thanks to Dyalog Classic

\$\endgroup\$
3
\$\begingroup\$

Retina 0.8.2, 58 bytes

\d+
$*
,(1*)(1*)(?=,\1(1*))
,$2$3
(1*)(,(?!1\1)1*)*,.*
$#2

Try it online! Link includes test cases. 0-indexed. Takes the durability first followed by the list of heights. Explanation:

\d+
$*

Convert to unary.

,(1*)(1*)(?=,\1(1*))
,$2$3

Take the absolute difference between each height and the next ($2 is for the positive difference, $3 for the negative). Note that the last height remains in the input.

(1*)(,(?!1\1)1*)*,.*
$#2

Match the durability and as many differences that don't exceed the durability, then replace everything with the count of those differences. (The comma is necessary to avoid matching the last height.)

\$\endgroup\$
3
\$\begingroup\$

x86-16 machine code, 17 bytes

00000000: 33ff 47ac 2a04 7302 f6d8 3ac4 7702 e2f2  3.G.*.s...:.w...
00000010: c3                                       .

Listing:

33 FF       XOR  DI, DI         ; zero jump counter 
        BOOK_LOOP: 
47          INC  DI             ; increment jump counter 
AC          LODSB               ; AL = current height 
2A 04       SUB  AL, [SI]       ; AL = AL - next height 
73 02       JAE  IS_POS         ; is positive? 
F6 D8       NEG  AL             ; if not, negate to get abs value 
        IS_POS: 
3A C4       CMP  AL, AH         ; over threshold? 
77 02       JA   DONE           ; if so, push the AZ-5 button 
E2 F2       LOOP BOOK_LOOP      ; otherwise, keep plugging 
        DONE: 
C3          RET                 ; return to caller

Input list at [SI], length in CX, threshold in AH. Output stopping index (1 based) in DI.

About as vanilla asm as you can get. Any time I tried to get clever it was more bytes...

\$\endgroup\$
1
  • 1
    \$\begingroup\$ "Any time I tried to get clever it was more bytes..." Yup, that's pretty much par for the course, in my experience. That's why it's often much more fun (not to mention more practical) to optimize for speed. As a case in point, the shortest way to get an absolute value is always going to be test-and-branch, as you've done here, but it's almost never going to be the most efficient way to do so. That's the crazy (and, in some ways, fun) thing about CISC insn sets like x86 (and, to a lesser extent, even pure RISC ISAs): more bytes of code can counterintuitively net a huge performance win. \$\endgroup\$ Feb 3, 2022 at 3:38
3
\$\begingroup\$

R, 43 42 bytes

Edit: -1 byte thanks to pajonk (who anyway found a better approach...)

function(x,y)which(c(abs(diff(x))>y,T))[1]

Try it online!

\$\endgroup\$
4
  • \$\begingroup\$ Indexing to seq looked weird - which feels better I think: -1 byte. \$\endgroup\$
    – pajonk
    Feb 5, 2022 at 20:01
  • \$\begingroup\$ But if we want something weird-looking, here's something using match for another -1 byte, \$\endgroup\$
    – pajonk
    Feb 5, 2022 at 20:03
  • \$\begingroup\$ @pajonk - Great. You should post the match one. I was uselessly trying a match(x,,nomatch=length(x), and completely missed your trick. Well done (and I've no idea how i made the seq instead of which blunder...) \$\endgroup\$ Feb 6, 2022 at 7:33
  • \$\begingroup\$ Posted, thanks! \$\endgroup\$
    – pajonk
    Feb 6, 2022 at 8:29
3
\$\begingroup\$

R, 41 bytes

function(x,y)match(T,c(abs(diff(x))>y,T))

Try it online!

Based on @Dominic van Essen's answer, so test harness taken from there.

The idea emerged when golfing Dominic's answer and using which: "hmm, we need the first index and I remember that there's a function that returns only the first index (which is annoying in some challenges). Oh, it's match!"

\$\endgroup\$
3
\$\begingroup\$

Desmos, 96 50 47 bytes

- a whopping 46 bytes thanks to Aiden Chow
- 3 bytes thanks to Aiden Chow again

L=l.length
\min(\{(l[2...]-l)^2>aa:[1...L],L\})

Probably not the right language, but I had a lot of fun coding this.
Receives a list l and durability a as input.
Online Version

\$\endgroup\$
17
  • \$\begingroup\$ Directly pasting this into Desmos will break the code. You need a backslash in front of every { and }. \$\endgroup\$
    – Aiden Chow
    Feb 2, 2022 at 1:38
  • \$\begingroup\$ Also, you can remove the commas for the list ranges (,..., -> ...). \$\endgroup\$
    – Aiden Chow
    Feb 2, 2022 at 1:42
  • \$\begingroup\$ length(l-1) is the same as length(l). Maybe you meant to write length(l)-1 instead? \$\endgroup\$
    – Aiden Chow
    Feb 2, 2022 at 1:43
  • \$\begingroup\$ Other tiny golfs: You can remove the :1 part in piecewise expressions. So, \{(condition):1,0\} can be replaced with \{(condition),0\} and it will do the same thing. The space between for and i can also be removed. If you write f(L)=L.length and then replace all the length functions in your code to f, you can shave off a byte. \le can be replaced with <=. \$\endgroup\$
    – Aiden Chow
    Feb 2, 2022 at 1:45
  • \$\begingroup\$ You can visit the Desmos Tips Page, where you will find many of the tips I've just described here plus some more tips. \$\endgroup\$
    – Aiden Chow
    Feb 2, 2022 at 1:52

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.