text:
99 bugs in the code
99 bugs in the code
The adaption of "99 bottles of beer on the wall" for computer science where the bugs increase instead of the bottles decreasing is often re-posted around the internet. Example T-Shirt Here.
I think it'll be interesting to see potential recursion and random number generation across a huge variety of languages and finding the most efficient ways to do it.
There's a fair few other challenges to do with 99 bottles of beer but none seem to have an increasing and decreasing number!
Challenge
Your program or function should take no input and then print

99 bugs in the code
99 bugs in the code
Take one down and patch it around
X bugs in the code
(blank line)

Where X is the previous integer minus 1 plus a random integer in the range [-15,5].
You can merge the minus 1 into the random integer, hence allowing the range [-16,4].
Ranges can be exclusive, so minus one plus (-16,6) or (-17,5).
The random integers don't have to be evenly distributed they just have to all be possible.
The program always starts with 99 bugs.
You can ignore the grammatical error of "1 bugs".
The program should stop when the number of bugs is 0 or negative and print

0 bugs in the code

There should never be a negative number of bugs. The ending should look like

Y bugs in the code
Y bugs in the code
Take one down and patch it around
0 bugs in the code
(blank line)
0 bugs in the code

A trailing new line is acceptable.

Your code can be a full program or a function.
There is no input.
The output should be to stdout or returned.
Warnings/errors in logs/STDERR are okay as long as STDOUT has the required text. See here for more info.

This is code-golf so the shortest code in bytes wins.
Example Output
Paste bin example output rigged for -11 bugs each time

Related: 1 2 (difference: in this challenge the output can be arbitrarily long).

why is merging the 1 in the random only allowed if the random distribution is uniform? It makes no difference (AFAICT), as rand(-15,5)-1 could get simplified to rand()*21 - 15 - 1 = rand()*21 - 16 for any random number generation implementation.

We always will start at 99 correct ?

@dzaima that's exactly what i assumed

@dzaima yes you're right. I'd got it in my head that it would affect the averages or something. I'll change it

@MuhammadSalman yep always starts at 99

A more realistic scenario would be if the sign of the random number was flipped!

I am disappointed, that the requirements don't include that the program must have a bug once a negative number is encountered, like crashing, overflowing to max int or similar ;).

@allo I guess in theory all the answers will crash if the random number keeps being positive!

"The random integers don't have to be evenly distributed they just have to all be possible." reminded me of https://xkcd.com/221/

Is the fact that the output isn't to match the metre of the original bugging anyone else, or is it just me?

It's a shame 99 has no random number generation.

Are trailing newlines allowed?

Title should be "Quantum Bugs in the Code"

Is the "continuously print" an actual requirement? (Some answers actually produce the whole string.)

"Warnings in logs are okay." Does this mean warnings (or errors) in stderr are acceptable?

How strict is the output format? In QBasic, it's WAY easier if the numbers are allowed to have a leading space.

@JonathanAllan I would prefer the whole string not all be printed at the end but I think it's a little late to enforce that now

Agreed - maybe edit the challenge to just say "print" then.

@DLosc That output format is HIGHLY preferred but I have allowed COBOL to have signs before numbers because formatting adds so many characters so I'll allow it in general for languages that struggle formatting numbers.

RE: @iamnotmaynard's question: I believe that the default is that if the chosen output is somewhere other than STDERR then any coincident STDERR may simply be ignored (This is along with the fact that we may choose to output to STDERR or as the top of the stack etc, and ignore other coincident output(s)) - I would suggest actually removing the requirement "The output should be to stdout or returned" (use defaults)

...also your comment "so for now I'm going to say they're not okay" would invalidate my Python 2 answer since it adhere's to the spec as written - it outputs to stdout - but performs a divide by zero to force an early exit.

As per @Giuseppe's question, are trailing newlines (plural) allowed?

@JayCe a single trailing new line is allowed

a single trailing new line is allowed: That would make the recent javascript and C# entries invalid judging from the TIO links.

@JayCe Yes they are invalid. The above wasn't a rule change, the main post always said "A trailing new line".

R, 182 140 138 135 bytes
n=99;while(n)cat(n,b<-" bugs in the code
",n,b,"take one down and patch it around
",n<-max(0,n-sample(21,1)+5),b,"
",c(n,b)[!n],sep="")

Try it online!
while being reasonably good at random number generation, R is terrible at strings and printing. JayCe found about a billion bytes, and continues to find new ways to golf this!

Where did JayCe find all those bytes? Was it just happenstance or was JayCe actively looking for them?

@StewieGriffing one billion and one :) from Jonathan Allan's Python solution

make it 133 then :) - made the non-solution into a solution and incorporated your savings

Isn't the +5 costing you another 2 bytes? why not just sample(26,6))?

@theforestecologist Welcome to PPCG ! I suggest you take a closer look at the question... there is a minus sign in front sample

@Giuseppe I saw your comment to the question re: newline at the beginning... I just realized I have one newline too many :(

Java 8, 161 160 bytes
v->{String s="",t=" bugs in the code\n";for(int i=99;i>0;s+=i+t+i+t+"Take one down and patch it around\n"+((i-=Math.random()*21+4)<0?0:i)+t+"\n");return s+0+t;}

-1 byte thanks to @JonathanAllan.
Try it online.
Explanation:
v->{                   // Method with empty unused parameter and String return-type
  String s="",         //  Result-String, starting empty
         t=" bugs in the code\n";
                       //  Temp-String we use multiple times
  for(int i=99;i>0;    //  Start `i` at 99, and loop as long as it's larger than 0
    s+=                //   Append to the result-String:
       i+t             //    The first line of the verse
       +i+t            //    The second (duplicated) line of the verse
       +"Take one down and patch it around\n"
                       //    The third line of the verse
       +((i-=Math.random()*21-4)
                       //    Decrease `i` by a random integer in the range [-16, 4]
         <0?0:i)       //    If `i` is now negative, set it to 0
        +t+"\n");      //    And append the fourth line of the verse
  return s             //  Return the result,
         +0+t;}        //  appended with an additional line for 0 at the very end

Seems you are not using r for anything?

Removing ,r appears to still work: Try it online!

@O.O.Balance Oops.. Not sure why I got that there.. >.> Thanks for noticing.

i-=...+5 saves one (although I think the range should be [-16 4] not [-15,5])

@O.O.Balance yes r is not used, because he is using java ;-)

@JonathanAllan It should actually be i-=...-4 instead of +4, but thanks for the -1 byte (and fixed range)!

Use Java 10 so you can replace everything with var ;)

@JacobG. The only thing I can replace with var in my answer is the int, which doesn't save anything I'm afraid. :) And I could change String s="",t="..."; to var s="";var t="...";, but that wouldn't save bytes either (in fact, it increases the byte-count by 1).

PowerShell, 137 135 133 131 bytes
$b=' bugs in the code';for($a=99;$a){,"$a$b"*2;"Take one down and patch it around";$a+=-16..4|Random;if($a-lt0){$a=0}"$a$b`n"}"0$b"

Try it online!
The "bugs in the code" section is saved into $b for later use. Sets $a to 99, enters a for loop on $a. First we create an array of two strings ," "*2, with the string being the "X bugs in the code".
Next is just the string "Take one down and patch it around". Then we increment $a by selecting a Random integer from the range [-16,4]. After that, we clamp $a to be at minimum zero using an if if($a-lt0){$a=0}. Then the string "Y bugs in the code".
Finally, after the loop is finished, we put the string "0 bugs in the code" onto the pipeline. All of those strings are gathered from the pipeline, and an implicit Write-Output gives us newlines between them for free.
Saved two bytes using a for loop instead of a while loop.
Saved two bytes by moving $b onto its own section.
Saved two bytes thanks to Adrian Blackburn.

You could replace $a=(0,$a)[$a-gt0]; with If($a-lt0){$a=0} for a couple of bytes

@AdrianBlackburn Thanks!

JavaScript (Node.js), 127 bytes
f=(i=99,t=` bugs in the code
`)=>i>0?i+t+`Take one down and patch it around
`+((i+=0|Math.random()*21-15)<0?0:i)+t+`
`+f(i):0+t

Try it online!

Explanation :
f = (                                          // start of our recursive function
    i=99,t=` bugs in the code                 // parameters, 1. num bugs , 2. text
`)                                           // using string literal end text with \n
=>                                          // start function
    i > 0 ?                                // if i is greater than 0
        i + t +                           // return value of i, value of t and
    `Take one down and patch it around   // and this text
    `                                   // + new line
    + (( i +=                          // and add
        0|Math.random()*21-15) < 0 ?  // remove decimal from value obtained by multiplying
                                     // random number (between 0 and 1) multiplied by 21
                                    // and then subtracting 15 from it
                                   // if that value is less than 0
        0 :                       // add 0 to i
        i                        // otherwise add value of i
        )                       // end the parenthesis
    + t                        // add value of t to that
    + `\n`                    // along with a new line
    + f(i)                   // and repeat the process (this is recursive)
    :                       // if i > 0 condition not met then
        0 + t              // return 0 + t. Zero is there so the last line can be
                          // repeated

Thanks to @tsh for the idea of recursion and implementation (saved some bytes)
Any suggestions to golf this further are welcome.

Use recursion save some bytes

Why was 0+ removed? It seems to be required output.

@tsh : Is it ? I didn't read that part.

Python 3, 156 138 bytes
Thanks to Jonathan's Python 2 answer for the id trick
r=n=99
z='%d bugs in the code\n'
while n:x=n;r+=id(r);n-=min(n,r%21-4);print((z%x)*2+'Take one down and patch it around\n'+z%n)
print(z%n)

Try it online!
Explanation:
r=n=99       #Initialise r and n to 99
z='%d bugs in the code\n'  #Save n
while n:     #Loop while n is not 0
    x=n      #Save value of n
    r+=id(r) #Modify value of r, which changes the hash value
    n-=min(n,r%21-4)  #Change n's value by a random number between 4 and -16
    print((z%x)*2+'Take one down and patch it around\n'+z%n)   #Print the message
print(z%n)  #And print the final line

05AB1E, 59 bytes
99[Ð16(4ŸΩ+¾‚{θ©3F“ÿ±À€†€€ƒË“Š}“ƒ¶€µ„‹€ƒš¡€•…¡“ªsõ®>#®]sDŠ»

Try it online!

JavaScript, 189 176 168 162 bytes
f=(x=99)=>{c=console.log;m=Math;a=` bugs in the code
`;c(x+a+x+a+"Take one down and patch it around"+(x=m.max(x+m.ceil(m.random()*21-15),0))+a)
x?f(x):c(`
`+x+a)}

Try it online!
Thanks for Muhammad Salman for the missing console.log replacement, and for Oliver for the x test improvement
Thanks for l4m2 for golfing this by 8 bytes

I'm no node expert, but I believe "The program should stop when the number of bugs is 0 or negative" means you need x<=0?console.log("\n"+0+a):f(x) at the end.

that's what i do with x==0?console.log("\n"+x+a):f(x)

Ok, sorry. One more thing: if you need to recurse in an anonymous function, you need to explicitly name it (+2 bytes)

You can ignore those 2 bytes, you'll see that in most of JS answers here

Not if the function requires itself to be named f.

can't that last "console.log" be replaced with "c"?

@Therandomguy : saved a ton of bytes

Also @NoOneIsHere is right. You do need that f declaration. Voted down till updated to fix that. (Also my link needs an update too)

The point I'm trying to make here is your code doesn't work if the function isn't called f, which you can't assume.

@Oliver : Yeah, you could, but you should tell the author and not me

@Therandomguy : Thanks for update. I undownvoted this

(x+a).repeat(2) for what no direct add?

Could you save a byte using with? TIO

Node.js is not necessary here. It's just pure JavaScript (version 6?)

Charcoal, 81 bytes
≔⁹⁹θ≔”⧴"pWº⁴tＳn/{yBⅈ⁺”ζＷ›θ⁰«×²﹪ζθ”↶0⪫\`3+¤⸿Zν(z¬hＬÀＴj'ZXεＰraF”≧⁺⁻⁴‽²¹θ﹪ζ×θ›θ⁰¶»﹪ζ⁰

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

Start with 99 bugs in the code.
≔”⧴"pWº⁴tＳn/{yBⅈ⁺”ζ

Save the compressed string "%d bugs in the code\n".
Ｗ›θ⁰«

Repeat while there are a positive number of bugs remaining.
×²﹪ζθ

Print the number of bugs in the code twice.
”↶0⪫\`3+¤⸿Zν(z¬hＬÀＴj'ZXεＰraF”

Print "Take one down and patch it around".
≧⁺⁻⁴‽²¹θ

Add a random number of bugs between -17 (exclusive) and 4 (inclusive).
﹪ζ×θ›θ⁰

Print the number of bugs remaining, or 0 if negative.
¶

Leave a blank line between verses.
»﹪ζ⁰

After the last verse, print 0 bugs in the code again.

Need that final repeated "0 bugs in the code"!

@SamDean Sorry I'd overlooked that, fixed.

COBOL (GnuCOBOL), 317 294 279 270 269 249 248 247 bytes
Using go to statements: 247 bytes
data division.working-storage section. 1 i pic S99 value 99.procedure division.a.perform b 2 times display"Take one down and patch it around"compute i=4+i- random*21 set i to max(0,i)perform b display""if i>0 go to a.b.display i" bugs in the code"

Try it online!
Ungolfed
data division.                     <-- Define the variables we want to use
working-storage section.           <-- Define global variables used in this
                                       program

1 i pic S99 value 99.              <-- Define variable i with datatype signed
                                       numeric and with two digits

procedure division.                <-- Define our program

a.                                 <-- Define label a, to jump to
    perform b 2 times              <-- Execute the procedure called 'b'
                                       twice, see below
    display "Take one down and..." <-- Display this sentence
    compute i =
        4 + i - (random * 21)      <-- Subtract from i some random value
    set i to max(0,i)              <-- If i is negative, then assign 0 to i

    perform b                      <-- Execute the procedure 'b'
    display ""                     <-- Display an empty string; needed
                                       because of the blank line
    if i > 0                       <-- If i is still greater than 0, then
                                       we're not done yet
        go to a.                   <-- and we'll jump back to 'a'

b.                                 <-- Define procedure called 'b'.
    display i " bugs in the code"  <-- Display the value of i and then the
                                       given string literal

Using the perform statement as loop control: 269 bytes
data division.working-storage section. 1 i pic S99 value 99.procedure division.perform until i=0 perform a 2 times display"Take one down and patch it around"compute i=4+i-(random*21)if i<0 compute i=0 end-if perform a display""end-perform.a.display i" bugs in the code"

Try it online!
Ungolfed
data division.                     <-- Define the variables we want to use
working-storage section.           <-- Define global variables used in this
                                       program

1 i pic S99 value 99.              <-- Define variable i with datatype signed
                                       numeric and with two digits

procedure division.                <-- Define our program

perform until i = 0                <-- Perform the following code until i = 0
    perform a 2 times              <-- Execute the procedure called 'a' twice,
                                       see below

    display "Take one down and..." <-- Display this sentence
    compute i =
        4 + i - (random * 21)      <-- Subtract from i some random value

    if i < 0                       <-- if i < 0
        compute i=0                <-- then assign 0 to i
    end-if
    perform a                      <-- Execute the procedure 'a'
    display ""                     <-- Display an empty string; needed because
                                       of the blank line
end-perform.

a.                                 <-- Define procedure called 'a'.
    display i " bugs in the code"  <-- Display the value of i and then the
                                       given string literal

Note: the last sentence is still printed, because COBOL executes the whole program, and after the perform until loop it "falls-through" the label a, executing its statements. This behaviour is similar to a switch case without break.

Thanks to tail spark rabbit ear, 1 byte has been saved by using the intrinsic function max instead of an if statement.
Thanks to tail spark rabbit ear, 1 byte has been saved by replacing the compute by the set statement.
Thanks to raznagul, 1 byte has been saved by rewriting the formula for the new number of bugs.

PS: The numbers are not exactly displayed as required, but COBOL is not that good at auto-converting numbers to a pretty textual representation.

Hi. Welcome to PPCG.

I think that minus 4 should be plus 4. I'm guessing you went for (i-(rand-4) == (i-rand+4). But there's no brackets so the sign needs to change.
Also can the signs of the numbers be removed or is that a feature of the language?
But nice work with a non gold friendly language!

@SamDean Thanks! I fixed that mistake. I got to admit that the actual random calculated was inspired from Kevin Cruijssen's answer. But he uses a compound assignment operator (-= in i-=Math.random()*21-4), which implies parenthesis around the whole righthand operand. I forgot to make them explicit, but it is now fixed, I think.

@MCEmperor looks good to me now!

Can't you use +4 and save the brackets?

@raznagul No, I can't, the compiler start whining.

@raznagul I came across this post of mine, and indeed, using +4 instead of -4 saved 1 byte!

229 bytes. It just reduces S of S99 and if i>0 compute i=0 from 249 bytes post.

@tailsparkrabbitear But the problem is that the number of bugs may increase while near zero, until the number of bugs is actually zero.

@mcemperor I meant to reduce if i<0 set 0 to i. Also I noticed that setting PIC to be 99 instead of S99 may fail, as 99 to suddenly a small number can occur; I think it should be 999 instead. TBH doesn't COBOL on TIO have something such as srand()?

@tailsparkrabbitear Well, thanks to you, 1 byte has been saved! I'm still testing with pic 999.

236 bytes but I don't think it completed. Can't I do something like i=max(0,-21*rand()+4+i) as in other languages using MOVE?

247 bytes.

Octave, 149 148 bytes
Saved one byte by changing randi(21) and %i to 21*rand and %.f. %.f ensures the output is a float with zero decimals (i.e. and integer).
Inserted a bunch of line breaks instead of commas and semicolons to ease readability. It feels wrong, but it's not longer than the one-liner.

x=99;do(p=@(i)printf('%.f bugs in the code\n',i))(x)
p(x)
disp('Take one down and patch it around')
p(max([0,x+=21*rand-17]))
disp('')until x<1
p(0)

Try it online!
Explanation:
x=99;               % Initialize the number of bugs to 99
do ...  until x<1   % Loop until the number of bugs is less than 1
 (p=@(i)printf('%.f bugs in the code\n',i))(x)  % Create a function handle p that takes
                                                % the number of bugs as input and outputs
                                                % the string x bugs ... \n
 p(x)                % Call that function with the same number of bugs to get two lines
 ,disp('Take on down and patch it around')       % Outputs that line, including a newline
 ,p(max([0,x+=21*rand-17]))                    % Call p again, while updating the number
                                                 % of bugs. The number of bugs will be
                                                 % the old one plus the random number, or 0
                                                 % if it would have turned negative
 ,disp('')        % A newline
p(0)              % Finally, the last single line.

Using p((x+=21*rand-17)*(x>0) instead of max saves a byte, but the last line outputs -0 bugs ... instead of 0 bugs. It works with randi(21)-17, but then it's the same length as the one above. Try it online!

Python 2, 151 bytes
Nice trick j=i+max(-i,randint(-16,4)) by Jo King, exploiting allowed uneven distribution
Saved couple bytes thanks to Mnemonic
from random import*
i,s=99,'bugs in the code\n'
while i:j=max(0,i+randint(-16,4));print i,s,i,s,'Take one down and patch it around\n',j,s;i=j
print i,s

Try it online!

You can save a byte by using j=max(0,i+randint(-16,4)).

Also, it's 'bugs in the code'.

Using 0 to compare wiil make not all numbers possible. Thanks for nothing 'the' :D

Same trick as my answer, 151 bytes

They're not possible anyway.  You're not allowed to go below 0.

@DeadPossum : which numbers will be made impossible ?

@Mnemonic Now I get it, didn't pay enough attention(

C,  169  165 bytes
Thanks to @ceilingcat for saving four bytes!
*s=" bugs in the code";f(i,j){for(i=99;i>0;i=j)printf("%d%s\n%d%s\nTake one down and patch it around\n%d%s\n\n",i,s,i,s,(j=i+rand()%19-15)<0?0:j,s);printf("0%s",s);}

Try it online!

I think that limit's inclusive. It should be %21.

161

VBA: 212 163 Bytes
This solution is based on the one by Chronocidal posted yesterday.  This my first post and I don't have enough reputation to comment on his post.
This revision contains two enhancements.

Using While/Wend instead of For/Next saves a few characters.
Calling a Sub named with a single character is shorter than GoSub and the Exit Sub and Return lines needed to support it.

Edit:
 3. Removed whitespace and characters that the VBA editor will automatically add back in.  See Tips for golfing in VBA
 4. Added suggestions by @EricF, then saw his paste bin algorithm was even smaller so I replaced my algorithm with his and removed whitespace.  A key change was appending vbLF to the output string so Debug.Print did not have to be called as often.  Kudos to EricF.

Sub b()
s=" bugs in the code"&vbLf
c=99
While c
Debug.? c &s &c &s &"Take one down and patch it around
c=c+5-Int(Rnd()*20)
c=IIf(c<0,0,c)
Debug.? c &s
Wend
End Sub

This was a fun challenge.  If you know of an online interpreter like TIO for VB6/VBScript/VBA please leave a comment.
If you want to test this code and have Microsoft Excel, Word, Access, or Outlook installed (Windows only), press Alt+F11 to open the VBA IDE.  Insert a new code module (Alt+I,M) and clear out Option Explicit.  Then paste in the code and press F5 to run it.  The results should appear in the Immediate Window (press Ctrl+G if you don't see it).

Welcome to the site!

You can get it down to 197 characters if you combine strings, use c instead of c>0 as your While condition, and use c=Iif(c<0,0,c) instead of If c<0 [...]: https://pastebin.com/nFGtGqdE

LaTeX, 368 304 293 287 245 240 bytes
While not really competitive compared to the other programs in terms of bytes, I just wanted to see how to do this in LaTeX.
\documentclass{proc}\newcount\b\b99\usepackage[first=-16,last=5]{lcg}\def~{\the\b\ bugs in the code\\}\def\|{\loop~~Take one down and patch it around\\\rand\advance\b\value{rand}\ifnum\b>0 ~\\\repeat\b0 ~\\~}\begin{document}\|\end{document}

More readable:
\documentclass{proc}               %shortest document class
\newcount\b                        %short variable name
\b 99                              %set the value to 99
\usepackage[first=-16,last=5]{lcg} %random number generator
%\the prints the value of the variable behind it
%\def is shorter than \newcommand and can redefine commands
\def~{\the\b\ bugs in the code\\}
\def\|{                            %the function
    \loop
        ~
        ~
        Take one down and patch it around\\
        %\rand creates a counter named rand and
        %stores the random value in it
        \rand \advance\b\value{rand}
        %if the counter is smaller than 0, it becomes 0
        \ifnum\b>0
            ~ \\                  %extra newline as required
    \repeat
    %if b is equal or smaller than 0, set it to 0
    \b 0
    ~ \\                          %then print like normal
    %extra print at the end
    ~
}
\begin{document}
    \|                             %calling the function
\end{document}

Improvements (per edit):

"x bugs in the code" is now a function instead of 4 lines
Rewrote the \if clause for the \repeat as a \else
Apparently \value{b}=x works for initialisation but not in the loop (instead of \setcounter{b}{x})
Apparently \relax should be used for point 3, but that can also be achieved by inserting a space. Removed the \else, used TeX commands instead of LaTeX as these are shorter, and replaced \' by ~.
Some code didn't need to be relaxed for some reason.

Welcome to PPCG.

Welcome to PPCG! I haven't run your code but shouldn't it be \ifnum\value{b}<1 rather than <0?

@JayCe: It doesn't really matter, once b is 0 it escapes the loop anyway. It may just be less intuitive that when b is 0 the else case is printed indeed, but effectively there is no difference I think.

@JayCe shortened the code, now it doesn't matter anymore ;)

SAS, 210 bytes
%macro t;%let b=bugs in the code;%let a=99;%do%until(&a<=0);%put&a &b;%put&a &b;%put Take one down, pass it around;%let a=%eval(&a-%sysfunc(ranbin(0,20,.3))+4);%if &a<0%then%let a=0;%put&a &b;%put;%end;%mend;%t

Ungolfed:
%macro t;
%let b=bugs in the code;
%let a=99;
%do%until(&a<=0);
  %put &a &b;
  %put &a &b;
  %put Take one down, pass it around;
  %let a=%eval(&a-%sysfunc(ranbin(0,20,.3))+4);
  %if &a<0%then%let a=0;
  %put &a &b;
  %put;
%end;
%mend;
%t

Can save a few bytes if warnings in the log are permitted (put the &a into the &b macro variable, but that generates an initial warning).

A few others have warnings so I'll go with they are allowed.

C (gcc), 141 137 bytes
I used preprocessor macros for great justice (warning: TV Tropes)
#define _(a)printf("%d bugs in the code\n"#a,i)
f(i){for(i=99;_(),i;i+=rand()%21-16,i*=i>0,_(\n))_(Take one down and patch it around\n);}

Try it online!

Clean, 245 234 bytes
import StdEnv,Math.Random,System.Time,System._Unsafe,Text
f[n,v:l]b|n>0=n<+b<+n<+b+"Take one down and patch it around\n"<+max 0v<+b+"\n"+f[v:l]b=0<+b

f(scan(+)99[n rem 20-16\\n<-genRandInt(toInt(accUnsafe time))])" bugs in the code\n"

Try it online!

Any chance you can remove the quotes at the start and end?

@SamDean Oh that's just a compiler option I forgot about. I'll throw that in.

PHP, 126 bytes
Run on the command line, using php -r 'code here':
$b=" bugs in the code
";for($x=99;print$x.$b,$x;)echo"$x{$b}Take one down and patch it around
",$x-=min($x,rand(-4,16)),"$b
";

Try it online!

ABAP, 295 bytes
...because why the heck not!
REPORT z.DATA:a(16),c TYPE qfranint.a = 'bugs in the code'.data(b) = 99.WRITE:/ b,a.WHILE b > 0.WRITE:/ b,a,/'Take one down and patch it around'.CALL FUNCTION
'QF05_RANDOM_INTEGER' EXPORTING ran_int_max = 21 IMPORTING ran_int = c.b = b + c - 17.IF b < 1.b = 0.ENDIF.WRITE:/ b,a,/,/ b,a.ENDWHILE.

It's certainly not competitive compared to other languages, but I even managed to slim it down from 330 bytes I wrote initially, so I count it as a personal win.
Since ABAP doesn't allow lines longer than 255 characters, I had to replace a space with a line break. On Windows this initially increased the size to 296 bytes due to CRLF, but it runs fine with just the LF in there. ABAP sure requires many spaces though, so this is no big deal.
WRITE simply dumps text the GUI, so I guess that is kind of like stdout? I could probably save some bytes here by using a structure or table, but due to how SAP handles mixed structures (containing chars and numbers) the approach I imagined would only work on non-Unicode systems... Which I personally consider a no-go, despite having access to both.
The function module for random numbers is the only one I could find in our system, I suppose there could be one with a shorter name or parameters. No idea!
More or less readable code, comments included:
REPORT z.
  "Define a (text) and c (random)
  DATA: a(16),
        c TYPE qfranint. "A stupid data type for a random INT

  "This is shorter than using VALUE (saves 3 bytes)
  a = 'bugs in the code'.
  "This is slightly shorter than doing ',b TYPE i' and 'b = 99'. (saves 2 bytes)
  data(b) = 99.

  "first line has to be outside of loop due to our exit condition (saved me ~5 bytes)
  WRITE: / b,a. "\n xx bugs in the code

  WHILE b > 0.
    WRITE: / b,a, "\n xx bugs in the code
    /'Take one down and patch it around'.

    "This ridiculous function for random numbers...
    "To save some bytes, I leave ran_int_min at it's default
    "of 1, and set the max to 21 instead, from which I remove
    "17 later on, resulting in a range of [-16,4]
    "Compare:
    "   ' - 17'              =  5 bytes
    "   ' ran_int_min = -16' = 18 bytes
    "(saves 13 bytes)

    CALL FUNCTION 'QF05_RANDOM_INTEGER'
        EXPORTING ran_int_max = 21
        IMPORTING ran_int = c.

    "Maximum number of bugs added:     4 = 21 - 17
    "Maximum number of bugs removed: -16 =  1 - 17
    b = b + c - 17.

    IF b <= 0.
        b = 0.
    ENDIF.

    WRITE: / b,a,/,/ b,a. "\nxx bugs in the code\n\nxx bugs in the code
  ENDWHILE.

Thanks for the challenge!
To my boss: Please don't fire me, I'm just educating myself!

Python 2,  138 134 133 131  127 bytes
-1 Thanks to Jo King (rearrange so as to use the logic bugs-=min(bugs,randomNumber) rather than bugs=max(0,bugs-randomNumber)). This allowed the force-quit using a division by zero error, saving a further 6 bytes!
r=n=99
t="bugs in the code\n"
while 1:r+=id(r);b=n;n-=min(n,r%21-4);print b,t,1/b|b,t,"Take one down and patch it around\n",n,t

Try it online!

Turns out I don't need to create tuples at all.

133 bytes

@JoKing Thanks! (I really should've spotted that since it's more like what I do in my Jelly answer.)

@JoKing ...which means we can force quit with a division by zero error to save --two-- six more :)

C#, 184 181 bytes
My first Code Golf answer!
(Based on Java answer from @Kevin Cruijssen)
Func<String>c=()=>{String s="",t=" bugs in the code\n";for(int i=99;i>0;s+=i+t+i+t+"Take one down and patch it around\n"+((i-=new Random().Next(21)-4)<0?0:i)+t+"\n");return s+0+t;};

Try it online!

Welcome to PPCG :)

T-SQL, 188 bytes
DECLARE @ INT=99,@b CHAR(18)=' bugs in the code
'a:PRINT CONCAT(@,@b,@,@b,'Take one down and patch it around
')SET @+=5-22*RAND()IF @<0SET @=0PRINT CONCAT(@,@b,'
')IF @>0GOTO a;PRINT '0'+@b

SQL allows returns inside string literals, so that helps.
CONCAT() does an implicit conversion to text so I don't have to worry about CAST or CONVERT.

Jelly, 61 bytes
;“,Ȥm46Ṛṛ⁽eɼḞF»
ÇȮ“"ḃḲɠ⁼ċTṪʠ/Ạ⁺ṗḍ^ẸƘⱮṖ8»20X+_«¥©17Ç⁷®ßÇ®?
99Ç

A niladic link which also works as a full program.
Try it online! (output is flushed after execution is complete but it prints paragraph by paragraph)
How?
;“,Ȥm46Ṛṛ⁽eɼḞF» - Link 1, helper to construct count-text: number
 “,Ȥm46Ṛṛ⁽eɼḞF» - compressed string (list of characters) = " bugs in the code\n"
;               - concatenate the number with that list of characters

ÇȮ“"ḃḲɠ⁼ċTṪʠ/Ạ⁺ṗḍ^ẸƘⱮṖ8»20X+_«¥©17Ç⁷®ßÇ®? - Link 2, print stuff: number
Ç                                         - call the last Link (1) as a monad
 Ȯ                                        - print and yield that
                                          - ...at this point that is then printed again
                                          -    implicitly due to the start of a new leading
                                          -    constant chain below
  “"ḃḲɠ⁼ċTṪʠ/Ạ⁺ṗḍ^ẸƘⱮṖ8»                  - compressed string (list of characters)
                                          -     = "Take one down and patch it around\n"
                                          - ...once again an implicit print, same reason
                        20                - twenty
                          X               - random int from [1,20]
                           +              - add the left argument, the number
                                17        - seventeen
                              ¥           - last two links as a dyad:
                             «            -   minimum (of rand[1,20]+n and 17)
                            _             -   subtract
                               ©          - copy this newNumber to the register
                                  Ç       - call last Link (1) as a monad = f(newNumber)
                                          - here we get another implicit print, same reason
                                   ⁷      - a new line character
                                          - yet another implicit print, same reason
                                    ®     - recall newNumber from the register
                                        ? - if...
                                       ®  - ...condition: recall from register again
                                          -               (i.e. if non-zero)
                                     ß    - ...then: call this Link (2) as a monad
                                          -          = Link 2(newNumber)
                                      Ç   - ...else: call the last Link (1) as a monad
                                          -          = Link 1(0) (since newNumber=0)

99Ç - Main Link: no arguments
99  - yep, you guessed it, ninety nine
  Ç - call the last Link (2) as a monad

JavaScript, 138 bytes
_=>(I=i=>`Take one down and patch it around
${l=(i>0?i:0)+` bugs in the code
`}
`+l+l+(i>0&&I(i+Math.random()*21-15|0)))(99).slice(55,-25)

f=

_=>(I=i=>`Take one down and patch it around
${l=(i>0?i:0)+` bugs in the code
`}
`+l+l+(i>0&&I(i+Math.random()*21-15|0)))(99).slice(55,-25)

console.log(f())

QB64, 134 bytes
From my brother.
S$="bugs in the code":I=99:WHILE I>0:?I;S$:?I;S$:?"Take one down and patch it around":I=I+INT(RND*21)-15:I=-(I>0)*I:?I;S$:?:WEND:?I;S$

Pyth, 94 92 bytes
J99WJ%jb[K"%d bugs in the code"K"Take one down and patch it around"Kk)[JJ=JeS,Z+J-O21 16;%KZ

Try it online

Previous version: 94 bytes
J99WJp%jb[K"%d bugs in the code"K"Take one down and patch it around"K)[JJ=JeS,Z+J-O21 16)b;%KZ

Perl, 132 bytes
$c=" bugs in the code
";for($i=99;$i>0;$i+=~~rand(21)-16){print$t.$/,($t=$i.$c)x2,"Take one down and patch it around
"}print"0$c
"x2

VBA: 225 233 Bytes
Sub b()
For c = 99 To 0 Step -1
GoSub d
GoSub d
Debug.Print "Take one down and patch it around"
c = c + 5 - Int(rnd() * 20)
If c < 0 Then c = 0
GoSub d
Debug.Print
Next c
Exit Sub
d:
Debug.Print c & " bugs in the code"
Return
End Sub

{EDIT} Added the missing rnd()*
Notes:
Uses GoSub to print the triplicated line, because it's slightly shorter than assigning the line to a variable and Debug.Printing it.
Debug.Print without any arguments prints an empty line (no need for a Null or an empty string)
A WorksheetFunction.Max line would be too long, so I used an "if less than" to prevent negatives.

With indentation and comments
Sub b()
    For c = 99 To 0 Step -1
        GoSub d '"# bugs in the code"
        GoSub d '"# bugs in the code"
        Debug.Print "Take one down and patch it around"
        c = c + 5 - Int(rnd() * 20)
        If c < 0 Then c = 0 'Non-negative
        GoSub d '"# bugs in the code"
        Debug.Print
    Next c
    Exit Sub
d: 'This is our GoSub bit
    Debug.Print c & " bugs in the code"
    Return
End Sub

That's a very efficient way to do random numbers!

@SamDean Not sure how I forgot to include the rnd() *  in there - I think I was busy tallying up if it was less characters to  Dim c% (i.e. "c is an Integer") and drop the Int()

haha no worries! Nice to see a VBA answer as I haven't used it in years!

Bash, 182 178 151 149 bytes
i=99;b=" bugs in the code";a(){ echo $i$b;};while((i>0));do a;a;echo Take one down and patch it around;i=$[i-$RANDOM%21+4];((i<0))&&i=0;a;echo;done;a

Try it online!
Ungolfed
i=99;                             # Var i as current number of bugs
b=" bugs in the code";            # b to shortcut our string

a() {                             # Define function 'a'
    echo $i$b;                    # to shortcut displaying or number of bugs
};

while((i>0)); do                  # Repeat as long as var i is greater than 0
    a;a                           # Execute 'a' twice
    echo Take one down and...     # Display some bugs taken down
    i=                            # Assign the following value to $i:
      $[i-$RANDOM%21+4]           # i minus a random value between -4 and 16
                                  #     $RANDOM is a bash builtin function to generate a
                                  #     pseudorandom value between 0 and 32767 inclusive.
                                  #     I have applied a modulo 21 to get 21 possible
                                  #     values. We take advantage of the allowed uneven
                                  #     distribution.

    ((i<0))                       # Perform the expression i < 0
           &&                     # and assign 0 to i only if the previous
             i=0                  # command completed successfully

    a                             # Execute 'a'
    echo                          # Display a blank line
done
a                                 # Execute 'a'

Thanks to muru and Sam Dean for their improvements, they saved me 31 bytes.

can't you remove the " -e" after the first echo?

removed the " -e" and a whitespace "; i" Try it online!

You can replace if [[ $i -lt 0 ]];then i=0;fi with ((i<0))&&i=0, [[ $i -gt 0 ]] with ((i>0)), i=$((i-$RANDOM%21+4)) with i=$[i-RANDOM%21+4] to get 152 bytes

@muru Thanks, I'll add it.

Ruby: 149 bytes
n=99;f=" bugs in the code\n";loop{puts"#{n}#{f}"*2+"Take one down and patch it around\n";(n+=rand -16..4)>0?puts("#{n}#{f}\n"):break};puts"0#{f}\n"*2

Should work in pretty much any version of Ruby >= 1.8
I think it might be possible to optimise the strings a bit more, but in general I'm pretty pleased with it - in particular the combo assignment/comparison/break statement and the abuse of optional brackets.
Note: the output technically has two trailing newlines; if that needs to be accounted for then it goes up by 4 characters.

Hello, and welcome to PPCG! We do count trailing newlines, but if it works on Linux you can only count the \n (no \r).

@NoOneIsHere Thanks :) I've updated my answer to clarify - I was referring to newlines on the output because the question specifies that having one is acceptable, but I wasn't sure about two.

I see. I think that's fine

Zsh, 133 bytes
b="%d bugs in the code
";for ((n=99;n;)){printf $b$b"Take one down and patch it around
$b
" n n n-=RANDOM%21-4,n=n\>0\?n:0};printf $b

Try it online!

This takes advantage of a few zsh features.

the alternative loop form: while list; do list; done can be written as while list {list}
If a format specifier in printf is numeric, the corresponding argument is evaluated as an arithmetic expression. So:

we get the value of n for free without using a $
n -= RANDOM % 21 - 4, n = n > 0 ? n : 0 is again evaluated without having to use $((...)), $[...] or similar. The > and ? had to be escaped.
The printf $b at the end evaluates an empty argument as 0 for %d.

Word splitting on parameter expansion is off by default, so I do not have to quote $b anywhere.

This allows allows me to write $b$b"Take..." instead of "$b${b}Take...".

Saved a few bytes by using actual newlines instead of \n, and for((n=99;n;)) instead of n=99;while ((n)).

I think it should be -4. "-=" looks like its compound so it does the +4 first then subtracts it all.

@SamDean oops, corrected.

javascript: 142
i=99
t=` bugs in the code
`;s='';while(i){s+=i+t+i+t+`Take one down and patch it around
`;i+=4-Math.random()*20|0;i=i<0?0:i;s+=i+t+`
`}s+=i+t;

Try it online

C (GCC), 138 bytes
i=99;main(v){for(;i-v--;printf("%d bugs in the code\n%s",i*=i>0,v?v+1?i-=rand()%21-4,"\n":"Take one down and patch it around\n":""))v%=3;}

Note: I managed to get it down to 141 bytes by myself (no external help); later I saved three bytes by applying a technique that ErikF used (i*=i>0 instead of i=i<0?0:i).  My original solo version:
i=99;main(v){for(;i-v--;printf("%d bugs in the code\n%s",i=i<0?0:i,v?v+1?i-=rand()%21-4,"\n":"Take one down and patch it around\n":""))v%=3;}

Nice golf! Also, you should provide a way to test the code - for example, a link to https://tio.run

Python 3, 187 bytes
from random import randint as r
p=print;b=99
def l(x): p(x if x > 0 else 0,"bugs in the code.")
while b > 0: l(b);l(b);p("Take one down and patch it around.");b+=r(-16,4);l(b);p("")
l(0)

So it turns out that dealing with IO/Random in Haskell is a nightmare, so changed the solution to Python. First attempt, not too great :( But at least it's working.

Python 3, 199 191 171 bytes
-8 bytes thanks to @Stephen
-20 bytes thanks to @Jo King
import random
x=99
l="bugs in the code\n"
p=print
while x>0:p(f"{x} {l}"*2+"Take one down and patch it around");x=max(0,x+random.choice(range(-16,5)));p(f"{x} {l}")
p(0,l)

Try it online!

191 bytes by putting the while body on one line and using import random and random.choice

Assign print to a variable, join the prints, and actually moving the while loop to one line. 171 bytes

SAS 153 146 145 bytes
data;a=99;b='bugs in the code';do while(a>0);put a b/a b;put'Take one down and patch it around';a=max(a+int(ranuni(0)*20-16),0);put a b/;end;run;
The original version is Joe's answer, thanks him.

You have to specify the language and the length in bytes (since it is code golf). Also, you have to at least try to golf it, e.g. remove unnecessary spaces or newlines.

@Bubbler Sorry, it is just a variant version by Joe: SAS, 210 Bytes. And I will try to golf it only if I know better how to edit my answer.

@whymath Edit by pressing the edit button. Also, if this is a small improvement in another user's answer, submit it as a comment instead, which you can do after obtaining a small amount of reputation from upvotes.

Thanks, @lirtosiast .kind of difficult cause I am not so good at this operation. By the way, why some answers' title also have a link? I mean, the name of the language.

@JonathanFrech okay, I already handled this.

Julia 0.7, 123 115 bytes
~n="$n bugs in the code"
!(n=99,m=max(0,n-rand(-4:16)))=n>0?[~n;~n;"Take one down and patch it around";~m;"";!m]:~n

Try it online!
!() returns a vector of strings (for each line)

Japt, 124 123 121 120 116 110 107 bytes
U=U||99P=` Þï  e ¬¸`OpU+POpU+P  Op`Take e Üµ, p®  ÂÐ` U=Mr0-15,5 +U-1U=Uc  (U>0 ?(OpU+P+R ,ßU  :Oo0+P

Try it online!

I'm guessing I need some headers/footers for it to work in TIO? Try it online!

Fixed Try it online!

@SamDean it looks like there are non-printing characters in the compressed string that aren't getting copied, it works in the TIO I posted. Here is the difference: https://www.diffchecker.com/MATxOdMv

Strings looking good now! You do need to change that "," for " and" though! "Take one down and patch it around"

Oh, didn't notice there was another Japt solution when I posted mine. Can see quite a few potential savings here but I'm on my phone so they'll have to wait 'til the morning. Welcome to PPCG, and Japt :)

Python 3, 144 bytes
from pylab import*
s='bugs in the code\n'
X=99
while X>0:i=randint(-16,5);print(X,s,X,s,'\ntake one down and patch it around',max(X+i,0),s);X+=i

Formatting is incorrect - the leading spaces may be ok if you ask, but this misses some new lines and does not print the final extra "0 bugs in the code" as required.

Red, 166 163 bytes
b: 99 forever[if b > 1[print[b t:{bugs in the code}s:"^/"b t
s{Take one down and patch it around}]if
0 > b: b + 4 - random 20[prin[0 t s s 0 t]break]print[b t s]]]

Try it online!
More readable:
b: 99
t: {bugs in the code}
s: "^/"
forever [
    if b > 1 [
        print [ b t s b t s {Take one down and patch it around} ]
        if 0 > b: b + 4 - random 20 [
            prin [ 0 t s s 0 t ]
            break
        ]
        print [ b t s ]
    ]
]

.COM opcode, 137 bytes
0000h: BE 63 00 E8 3B 00 85 F6 75 01 C3 E8 33 00 B2 61
0010h: CD 21 0F C7 F0 F7 26 87 01 01 D6 83 EE 10 73 02
0020h: 31 F6 E8 1C 00 B2 5E CD 21 EB D8 99 F7 36 85 01
0030h: 85 C0 74 05 52 E8 F3 FF 5A B4 02 80 CA 30 CD 21
0040h: C3 89 F0 E8 E5 FF B4 09 BA 4D 01 EB F1 20 62 75
0050h: 67 73 20 69 6E 20 74 68 65 20 63 6F 64 65 0D 0A
0060h: 24 54 61 6B 65 20 6F 6E 65 20 64 6F 77 6E 20 61
0070h: 6E 64 20 70 61 74 63 68 20 69 74 20 61 72 6F 75
0080h: 6E 64 0D 0A 24 0A 00 15 00

        org 100h

        mov si, 99
lp:     call put2
        test si, si
        jnz @f
            ret
        @@:
        call put2
        mov dl, str2 - 256
        int 33
        rdrand ax
        ;mov ax, 65536*14/21+1
        mul [twentyone]
        add si, dx
        sub si, 16
        ;lea si, [esi+edx-16]
        jnc @f
            xor si, si
        @@:
        call put2
        mov dl, str2 - 256 - 3
        int 33
        jmp lp

put1:   cwd
        div [ten]
        test ax, ax
        jz @f
            push dx
            call put1
            pop dx
        @@:
        mov ah, 2
        or dl, 48
int33:  int 33
        ret

put2:   mov ax, si
        call put1
        mov ah, 9
        mov dx, str1
        jmp int33

str1:   db ' bugs in the code', 13, 10, '$'
str2:   db 'Take one down and patch it around', 13, 10, '$'
ten     dw 10
twentyone dw 21

p.s. with upper 60000+, if not consider it running up so high (in 250) can save some bytes

Japt -R, 83 79 75 73 bytes
Includes a trailing newline
#c
` Þï  e ¬¸
`
@§T}a@Np[UVUV`ìÇ¦ÓnÓlp®äNh
`qÊ¸TwU±Gn#ö¹V]¬ÃpViT

Test it

Explanation
#c                                         :99
\n                                         :Assign to variable U
`...`                                      :The compressed string " bugs in the code\n"
\n                                         :Assign to variable V
        [UVUV                  V]          :Build an array with U as the 1st & 3rd elements,
                                           : V as the 2nd, 4th & 7th
                                           : and the following as the 5th & 6th:
             `...`                         :  The compressed string "Takeloneldownlandlpatchlitlaround\n"
                  qÊ                       :   Split on "l"
                    ¸                      :   Join with spaces
                      w       ¹            :  Maximum of
                     T                     :   0 and
                           #               :    21
                             ö             :    Random number in the range [0,21)
                          n                :    Subtract
                         G                 :    16
                       U±                  :    Add to U
                                 ¬         :Join to a string
      Np                                   :Push to N, initially an empty array
@  }a@                            Ã        :Repeat until
 §T                                        :  U is less than or equal to 0
                                   p       :Push
                                    ViT    :  V prepended with 0
                                           :Implicitly join with newlines and output

Ruby, 128 bytes
N=99
def f;puts"#{N} bugs in the code"end
(f;f
puts"Take one down and patch it around"
N-=[N,15-rand(21)].min
f
puts)while 0<N
f

Try it online!

C# (.NET Core), 175 bytes
var s="";var r=new Random();for(int p=99;p>0;){var d=" bugs in the code\n";s+=p+d+p+d+"Take one down and patch it around\n";p+=r.Next(-17,5);s+=(p>0?p:0)+d+"\n";}return s;

Try it online!
C# uses a class for randomizing. Without the "Random" object, the response would be around 148 bytes. Using a for loop instead of a while loop removes one byte. using "new Random.Next()" will not work, since creating multiple Random objects within a loop wont make the Randomizer actually random.

Welcome to PPCG.

You need to add that final "0 bugs in the code" but nice answer!

BLZ 2.6, 155 bytes
b=99
while b>0
n={text.newline}
s=" bugs in the code"+n
p=(x->print(99+s+99+s+"Take one down and patch it around"+n+b+s))
p()
b=b+random(-16,5)
end
b=0
p()

Reminds me that I need to make "\n" a newline so I can save some of those characters from {text.newline}

anyway we can test that? also can you remove the space before "5" in the random function?

@SamDean Good call on the space, down to 155 bytes. You can test it by installing blz if you want. There's a guide here https://github.com/blazingkin/blz-ospl/wiki/Installation
You'd also have to checkout the v2.6 branch

Clojure, 192 188 bytes
#(loop[b 99](def s"bugs in the code")(printf"%s %s\n%s %s\nTake one down and patch it around\n"b s b s)(def n(max(+ b(rand-int 21)-16)0))(println n s"\n")(if(= n 0)(println n s)(recur n)))

Try it online!
Explanation
#(loop [b 99] ; Initialize a loop with b=99
  (def s "bugs in the code") ; Define a variable s that equals "bugs in the code"
  (printf "%s %s\n%s %s\nTake one down and patch it around\n" b s b s) ; Prints
    ;    "99 bugs in the code
    ;     99 bugs in the code
    ;     Take one down and patch it around" with the correct formatting.
  (def n (max (+ b (rand-int 21) -16) 0)) ; Let n = max(b+<some random number between -16 and 4 inclusive>, 0) This prevents negative numbers by replacing them with 0
  (println n s "\n") ; Prints "<n> bugs in the code" followed by an extra newline
  (if (= n 0) ; If n equals 0
    (println n s) ; Prints "<n> bugs in the code"
    (recur n))) ; Otherwise run the loop again with b=n

Dart, 173 169 bytes
import'dart:math';f({n=99,m=' bugs in the code\n'}){while(n>0){print('$n$m$n$m\Take one down and patch it around');n=n+Random().nextInt(20)-16;n=n<0?0:n;print('$n$m');}}

Try it online!
Almost competing with other Java-like languages for once

authors: n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳


text:
Smallest possible version of abs
The abs() function in most languages does one thing: give the positive version of the input. Most of the times this is done using something similar to
int
abs (int i)
{
    return i < 0 ? -i : i;
}

I was wondering if there is any way to do this with less bytes.
Note that this doesn't have to be more efficient, just smaller
Edit: i forgot to add that you can't use the abs() function in your language

So basically are you asking to codegolf the abs function, without using it ?

I'm afraid not. In most languages abs(i) is the shortest, and for those languages that require Math.abs(i) like Java, .NET, JS, etc. i<0?-i:i is the shortest.

basically, yes. I was just wondering what other languages have to offer when it comes to making this as small as possible

@DavinMiler Ah wait. You meant this as a challenge without using the builtin abs. Not a tips question to see if there is anything shorter than i<0?-i:i as alternative?

What i meant was: create the smallest possible version of abs, without using abs or i<0?-i:i

@DavinMiler How about i<0?i*-1:i? ;)

@KevinCruijssen haha, nice one

@user202729 this one allows certain operators, mine let's you use all

Retina, 2 bytes
-

Try it online!
Just remove the minus sign...

Works in QuadR too: Try it online!

TI-Basic, 3 bytes
√(AnsAns

Square root of input * input. Alternatively, √(Ans² is also 3 bytes.

R, 8 bytes
(x^2)^.5

Try it online!
thanks to @Giuseppe

Former, 1 byte longer version :
R, 9 bytes
x*sign(x)

Try it online!

(x^2)^.5 is 8 bytes. Another 9-byter (if we don't care about vectorization) is max(x,-x) or if we do care about vectorization, pmax(x,-x) for 10 bytes.

Although of course abs in R returns the magnitude of complex inputs, so none of these quite works the same as the R version.

Whitespace, 48 47 bytes
[N
S S N
_Create_Label_LOOP][S S S N
_Push_0][S N
S _Duplicate][T N
T   S _Read_STDIN_as_character][T   T   T   _Retrieve][S N
S _Duplicate][S S S T   S T T   S T N
_Push_45_-][T   S S T   _Subtract][N
T   S N
_If_0_jump_to_Label_LOOP][T N
S S _Print_as_character][N
S N
N
_Jump_to_Label_LOOP]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.
Try it online (with raw spaces, tabs and new-lines only).
Explanation in pseudo-code:
Start LOOP:
  Character c = STDIN as character
  if(c == '-')
    Go to next iteration of LOOP
  Print c
  Go to next iteration of LOOP

Old 48 bytes answer:
[S S S N
_Push_0][S N
S _Duplicate][T N
T   T   _Read_STDIN_as_integer][T   T   T   _Retrieve][S N
S _Duplicate][N
T   T   S N
_If_negative_jump_to_Label_NEG][N
S N
N
_Jump_to_Label_PRINT][N
S S S N
_Create_Label_NEG][S S T    T   N
_Push_-1][T S S N
_Multiply][N
S S N
_Create_Label_PRINT][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.
Try it online (with raw spaces, tabs and new-lines only).
Explanation in pseudo-code:
Integer i = STDIN as integer
if(i is negative)
  i = i * -1
  Jump to function PRINT
else
  Jump to function PRINT

function PRINT:
  Print i as integer to STDOUT

05AB1E, 2 bytes
nt

Try it online.
Explanation:
n     # Square
      #  i.e. 5 → 25
      #  i.e. -5 → 25
 t    # Square-root
      #  25 → 5

APL (Dyalog Unicode), 3 bytesSBCS
There are a few interesting approaches to this. All are anonymous tacit prefix functions. H.PWiz added two more.
⊢×× The argument multiplied by its sign. Try it online!
⊢⌈- Max of the argument and its negation. Try it online!
⊢∧× The LCM of the argument and its sign. Try it online!
⊢∨- The GCD of the argument and its negation. Try it online!
⊢÷× The argument divided by its sign. Try it online! Handles complex numbers but needs ⎕DIV (Division method) set to 1.

Also ⊢∧× and ⊢∨-

sed, 5 bytes
s/-//

Strip the negative sign

Java 8, 13 bytes
n->n<0?n*-1:n

Try it online.
Boring, but can't be done shorter without Math. or using -n directly (a.f.a.i.k.).

I don't think there is any restriction for -n

@Therandomguy There is, but it's in the comments instead of the challenge..

J, 2 bytes
Anonymous tacit prefix function.
%* The argument (implicit) divided by its sign. Try it online! Handles complex numbers as well.

Python 2, 18 bytes
lambda x:max(-x,x)

Try it online!
Previous (20 bytes)
lambda x:(x,-x)[x<0]

Try it online!

Japt, 2 bytes
Multiply input by its sign.
*g

Try it
Another square/root solution.
²q

Try it
Slightly less trivial 4 byte solution: convert to string, remove non-digit characters and convert back to integer. Or, if input can be taken as a string, this one can simply be r-.
sr\D

Try it

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Use that goodn't meme
There is currently a meme on the internet that consist of taking a sentence, reverse the meaning and adding n't at the end. For example, I am small becomes I am talln't
Challenge
For the sake of the challenge, we'll simplify this : Your task will be to detect whenever there is a negation in a sentence, and replace it with the 'positive' one with n't added at the end. There will be some tricky parts that will be explained in the rules.
Rules

You have to take a String as input, and return a String as output.
Input will be a sentence in lowercase, with only . and , as punctuation marks.
You have to replace any no <any_word> or not <any_word> with <any_word>n't.
no/not have to be a word and not a substring : you don't have to change anything in none of those
If the word already finish with a n, you have to replace n't with 't : no plan become plan't and not plann't
When no or not isn't followed by any word, a punctuation mark  or another no/not, you have to replace it with yesn't.
compound words count as one word. so even if no-op contain the substring no, it doesn't contain the word no. So the result will be no-op and not -opn't.
You do not have to worry about grammar errors. For example, there is no way will result to there is wayn't.
No standard loopholes allowed.
This is codegolf, so the shortest code wins.

There are some examples, even if this challenge looks clearn't for now.
Examples

Input : i love codegolfing, but i do not like short programs.
  does this sentence makes sense ... of course no.
Output : i love codegolfing, but i do liken't short programs.
  does this sentence makes sense ... of course yesn't.
Input : you are not invited. get out.
Output : you are invitedn't. get out.
Input : i am not ok, i have no plan and i have no gunn
Output : i am okn't, i have plan't and i have gunn't
Input : oh no no no i refuse.
Output : oh yesn't yesn't in't refuse.
Input : oh no no no, i refuse.
Output : oh yesn't yesn't yesn't, i refuse.
Input : i cannot believe this, you can't codegolf.
Output : i cannot believe this, you can't codegolf.
Input : oh no ... he did it again.
Output : oh yesn't ... he did it again.
Input : nn't is not a word, kevin. so this is not nn't.
Output : nn't is an't word, kevin. so this is nn'tn't.
Input : is it not clearn't for everyone
Output : is this clearn'tn't for everyone
Input : this is non't sense ...
Output : this is non't sense ...

In the introduction, shouldn't I am small become I am bign't?

One point says "Input willl be [...] only with only . and ,".  Another refers to "no-op".  But that contains a "-".  So is "-" allowed or not?

Should no n result in nn't or n't?

no n sould result in n't because the 'word' n finish with a n.

@Soaku small, tall, big, tiny, large, long, short etc. are all used interchangeably. It doesn't really matter for the sake of the question. But the most logical antonym for small would be big, yes.

Retina, 86 70 65 bytes
T`-'`L
\bnot?\s+(?!not?\b)(\w+?)n?\b
$1n't
\bnot?\b
yesn't
T`L`-'

-16 bytes thanks to @Neil.
-5 bytes thanks to @ovs.
Try it online.
Explanation:
T`-'`L             # Replace all "-" with "A" and all "'" with "B" to store them

\bnot?             # Then replace the word "no" or "not",
 \s+               #  followed by 1 or more whitespaces,
 (?!not?\b)(\w+?)  #  followed by a word/letter that is not "not" or "no"
 n?\b              #  minus a single trailing "n" if there are any
$1                 # with: the word/letter
 n't               #  appended with "n't"

\bnot?\b           # Then replace any remaining loose "no" or "not"
yesn't             # with "yesn't"

T`L`-'             # And finally replace all "A" with "-" and all "B" with "'" again

I think this shouldn't be the case

@DeadPossum Yeah, thought about that myself just yet and have already asked OP if "nn't" is possible in the input.

This is strange too

@DeadPossum Ah, that's indeed a bug in my code. Will try to fix it. Thanks for noticing.

no non should be non't . Don't hate me, I'm just interested in retina ._.

@DeadPossum no non, no-op, and no nn't are some annoying edge cases.. But I think everything is fixed now (and my byte-count is doubled XD)

I think I've got it down to 70 bytes.

@Neil Thanks. Nice approach with the separated captured (n|(\w)).

L here is a shorthand for A-Z, saving 2 bytes over T`-'`AB and vice versa.

@Neil Ah ok, thanks for explaining. TIL. :) Not too familiar with Retina's builtins yet.

@DeadPossum Punctuate it properly

@ovs It gives the incorrect result for "i am not ok, i have no plan and i have no gunn" (incorrect for any "not/no" followed by a word that ends in an "n").

@ovs Umm, all n't are now prepending the words instead of appending. EDIT: Changing the * to + seems to work though (I think).

I really should have looked closer. I think this fails on no n now. The output should be n't but the program outputs nn't

@ovs Hmm, I figured it was supposed to be nn't. I'll ask OP to verify what to do with it.

Python 2, 208 123 113 146 bytes
lambda s:re.sub(r"\bnot?\b(?!['-])(\s(?!not?(\b)(?!['-]))([\w'-]+))?",lambda m:(m.group(3)or"yes")+"n't"[(m.group(3)or'')[-1:]=='n':],s)
import re

Try it online!
Lost a bunch of bytes because of words ending in n't or n. Either or is shorter, but handling both was longer.

JavaScript (Node.js), 95 bytes
s=>s.replace(/\bnot?\b( (?!not?\b)(['\w-]*(\w)))?/g,(a,b,s,t)=>(s||'yes')+(t=='n'?'':'n')+"'t")

Try it online!
Thank Rick Hitchcock for 2 bytes

Stax, 75 73 50 bytes
ä§▀t9lJ₧5M#|+4╖¼├n▌ ·=┌«∙£╣▀K╖¥y▐▲·(■◄╙→á╣ó•ô╓╢Θ₧○

Run and debug it

Japt, 72 bytes
F=_r"%bnot?%s+(?!not?%b)(%w+?)n?%b|%bnot?%b(?!['-])",@Y=Y||"yes"Y+"n't"}

Try it online!

For "yes-no maybe-so", it produces "yes - mayben't - so".

Java 8, 163 136 bytes
s->s.replaceAll("(^|[ ,.])not?(?= *([,.]|$|not?(?=$|[ ,.])))","$1yesn't").replaceAll("(^|[ ,.])not? ([\\w'-]+?)n?(?=$|[ ,.])","$1$2n't")

-27 bytes by creating a port of @recursive's Stax' answer.
Try it online.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Is this a Weyr matrix?
There's a type of n×n matrix W called the basic Weyr canonical form. Such a matrix is described by its blocks and has the following properties, using the following reference diagram:

the main diagonal blocks Wii are ni×ni matrices of the form λIni where Ini is the ni×ni identity matrix.
n1 ≥ n2 ≥ ... ≥ nr
the first superdiagonal blocks Wk-1,k for k ∈ 2..r are nk-1×nk matrices that are full column rank in row-reduced echelon form, or more simply put, Ink sitting on top of nk-1 - nk rows of zeros.
all other blocks are 0 matrices.

For example:

The main diagonal blocks (yellow) are such that the ni are 4, 2, 2, and 1.
The first superdiagonal blocks are in green.
The grey zone consists of all the other blocks, which are all 0.

For this challenge we will assume λ=1.
Input
A square matrix with 0s and 1s in any convenient format.
Output
Output one of two distinct values for whether the input matrix is Weyr or not Weyr.
Rules
This is code-golf. Fewest bytes in each language wins. Standard rules/loopholes apply.
Test cases
Presented as arrays of rows.
Weyr:
[[1]]
[[1,1],[0,1]]
[[1,0,1,0,0],[0,1,0,1,0],[0,0,1,0,1],[0,0,0,1,0],[0,0,0,0,1]]
[[1,0,0,1,0,0,0,0,0],[0,1,0,0,1,0,0,0,0],[0,0,1,0,0,1,0,0,0],[0,0,0,1,0,0,1,0,0],[0,0,0,0,1,0,0,1,0],[0,0,0,0,0,1,0,0,1],[0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,0],[0,0,0,0,0,0,0,0,1]]
[[1,0,0,0,1,0,0,0,0],[0,1,0,0,0,1,0,0,0],[0,0,1,0,0,0,0,0,0],[0,0,0,1,0,0,0,0,0],[0,0,0,0,1,0,1,0,0],[0,0,0,0,0,1,0,1,0],[0,0,0,0,0,0,1,0,1],[0,0,0,0,0,0,0,1,0],[0,0,0,0,0,0,0,0,1]]

Non-Weyr:
[[0]]
[[1,0],[1,1]]
[[1,0,0,1,0,0],[0,1,0,0,0,0],[0,0,1,0,0,1],[0,0,0,1,0,0],[0,0,0,0,1,0],[0,0,0,0,0,1]]
[[1,0,1,0,0],[0,1,0,0,0],[0,0,1,0,0],[0,0,0,1,0],[0,0,0,0,1]]
[[1,0,0,1,0,0,0,0,0],[0,1,0,0,1,0,0,0,0],[0,0,1,0,0,1,0,0,0],[0,0,0,1,0,0,0,0,0],[0,0,0,0,1,0,1,0,0],[0,0,0,0,0,1,0,1,0],[0,0,0,0,0,0,1,0,1],[0,0,0,0,0,0,0,1,0],[0,0,0,0,0,0,0,0,1]]

Your definition of weyr, matrix is very unclear.  In order to understand it I needed to first read the definition from wikipedia (which is not very clear either) and even then your definition is rather vague and ambiguous.   For one I would make it clearer what ni is and what it is mean to do, currently it is not very clear that a matrix is weyr if such ns exist and rather it seems like they are some property of the matrix.

Is it correct that the identity matrix is a Weyr-matrix?

The identity matrix is be a Weyr matrix with r = 1 and n_1 = n, so yes, albeit a degenerate one.

Suggested test case: [[1,0,0,1,0,0,0,0,0],[0,1,0,0,1,0,0,0,0],[0,0,1,0,0,1,0,0,0],[0,0,0,1,0,0,0,0,0],[0,0,0,0,1,0,1,0,0],[0,0,0,0,0,1,0,1,0],[0,0,0,0,0,0,1,0,1],[0,0,0,0,0,0,0,1,0],[0,0,0,0,0,0,0,0,1]]. I think it's falsy (but my answer fails to identify it as such).

The definitions you included suggest you only want to identify basic weyr matrices, and not general weyr matrices. Is this what you intended for this challenge?

@S.Klumpers what do you mean by degenerate? Did you mean trivial?

I meant to say it is a degenerate case, but I forgot that it could be confused with a degenerate matrix, which is of course not what I meant. So yeah trivial would have been a better choice of words.

I can’t exactly see how the ngn/k answer works, but I tried to write a purely iterative implementation, as opposed to the JS answer, in x86 machinecode that didn’t go so well. Should I post the Java code I tried to base it off as a non-competitive reference?

K (ngn/k), 91 88 84 80 81 bytes
{x~e|(-n)#'(0*x),'(!n)=\:,/(-1_b)+1_0{x#!y}':|-n-':|b:|\@[-1++/|\|+x|e:=n:#x;]\0}

Try it online!

Python 2, 270 bytes
lambda m,w=0:{w}&{0,len(m)}and I(m)or any(I([l[:i]for l in m[:i]])*I([l[i:j+i]for l in m[:j]])*(sum(sum(m[:i]+[l[:i]for l in m],[]))==2*i+j)and f([l[i:]for l in m[i:]],j)for i in range(w,len(m))for j in range(1,i+1))
I=lambda m:all(sum(l)==l[i]>0for i,l in enumerate(m))

Try it online!
Explanation:
Recursively checks blocks for identity and their superdiagonal blocks.
I checks if a matrix is an identity matrix
I=lambda m:all(sum(l)==l[i]>0for i,l in enumerate(m))

For each block of the input matrix, the function checks that it is an identity, and that there is another identity matrix block, to it's right.
The next iteration then looks at a block of that size.
{w}&{0,len(m)}and I(m)                # if the while matrix is an identity matrix,
                                      # return true (but only the first time or last block)
or
any(
 I([l[:i]for l in m[:i]])                         # the current block is identity
 *I([l[i:j+i]for l in m[:j]])                     # and, the smaller block to the right is identity
 *(sum(sum(m[:i]+[l[:i]for l in m],[]))==2*i+j)   # and everything below and to the right (not the
                                                  # smaller block), are 0
 and f([l[i:]for l in m[i:]],j)                   # and the remaining matrix is alse Weyr(recursively)
 for i in range(w,len(m))             # for each block size i
 for j in range(1,i+1)                # for each smaller right block of size j
)


text:
X Steps Forward, 1 Step Back
Here the first 100 numbers of an easy sequence:
0,1,0,2,1,4,3,7,6,11,10,16,15,22,21,29,28,37,36,46,45,56,55,67,66,79,78,92,91,106,105,121,120,137,136,154,153,172,171,191,190,211,210,232,231,254,253,277,276,301,300,326,325,352,351,379,378,407,406,436,435,466,465,497,496,529,528,562,561,596,595,631,630,667,666,704,703,742,741,781,780,821,820,862,861,904,903,947,946,991,990,1036,1035,1082,1081,1129,1128,1177,1176,1226

How does this sequence work?
n: 0 1     2           3     4     5     6     7     8      9       10      11      12

   0,      1-1=0,      2-1=1,      4-1=3,      7-1=6,       11-1=10,        16-1=15,
     0+1=1,      0+2=2,      1+3=4,      3+4=7,      6+5=11,        10+6=16,        15+7=22

a(0) = 0
For every odd n (0-indexed), it's a(n-1) + X (where X=1 and increases by 1 every time it's accessed)
For every even n (0-indexed), it's a(n-1) - 1

Challenge:
One of:

Given an input integer n, output the n'th number in the sequence.
Given an input integer n, output the first n numbers of the sequence.
Output the sequence indefinitely without taking an input (or taking an empty unused input).

Challenge rules:

Input n can be both 0- or 1-indexed.
If you output (part of) the sequence, you can use a list/array, print to STDOUT with any delimiter (space, comma, newline, etc.). Your call.
Please state which of the three options you've used in your answer.
You'll have to support at least the first 10,000 numbers (10,000th number is 12,497,501).

General rules:

This is code-golf, so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
Default Loopholes are forbidden.
If possible, please add a link with a test for your code.
Also, please add an explanation if possible.

Test cases:
Pastebin with the first 10,001 numbers in the sequence. Feel free to pick any you'd like.
Some higher numbers:
n (0-indexed)    Output:

68,690           589,772,340
100,000          1,249,975,000
162,207          3,288,888,857
453,271          25,681,824,931
888,888          98,765,012,346
1,000,000        124,999,750,000

Python 2, 32 28 25 bytes
lambda n:(~-n|1)**2/8+n%2

Try it online!
Returns the n-th number (0-indexed)

Excel, 31 bytes
Answer is 0 indexed.  Outputs the nthe number.
=(A1^2+IF(ISODD(A1),7,-2*A1))/8

The sequence described is ultimately just two sequences interlaced:
ODD:   (x^2+x+2)/2
EVEN:  (x^2-x)/2

Interlacing these into one 0 indexed sequence gives:
a = (x^2 - 2x)/8 if even
a = (x^2 + 7 )/8 if odd

Which gives:
=IF(ISODD(A1),(A1^2+7)/8,(A1^2-2*A1)/8)

which we golf down to the 31 bytes.

Using the same approach, 1 indexed gives 37 bytes:
=(A1^2-IF(ISODD(A1),4*A1-3,2*A1-8))/8

Jelly, 6 bytes
Rj-ḣ⁸S

Try it online!
0-indexed. Returns nth number.
Explanation:
Rj-ḣ⁸S Arguments: z
R      [1..x]: z (implicit)
 j-    Join x with y: ^, -1
   ḣ⁸  Take first y of x: ^, z
     S Sum: ^

JavaScript (Node.js), 23 bytes
x=>(7+(x-2|1)**2)/8-x%2

1-indexed. Try it online!
f(x) = f(x+1) + 1 if x is even
     = SUM{1..(x-3)/2} if x is odd

SUM{1..(x-3)/2}
= (1+(x-3)/2)*((x-3)/2)/2
= (x-1)*(x-3)/8
= ((x-2)^2-1)/8

Haskell, 40 38 37 bytes
scanl(flip($))0$[1..]>>=(:[pred]).(+)

Returns an infinite list, try it online!
Explanation
scanl takes three arguments f, init and xs ([ x0, x1 ... ]) and builds a new list:
[ a0 = init, a1 = f(a0,x0), a2 = f(a1, x1) ... ]
We set init = 0 and use the flipped ($) application operator (thus it applies ai to the function xi), now we only need a list of functions - the list [1..]>>=(:[pred]).(+) is an infinite list with the right functions:
[(+1),(-1),(+2),(-1),(+3),(-1),(+4),...

Interesting alternative, 37 bytes
flip having the type (a -> b -> c) -> b -> a -> c we could also use id :: d -> d instead of ($) because of Haskell's type inference the type d would be unified with a -> b, giving us the same.
Try it online!
Edit
-2 bytes by using (>>=) instead of do-notation.
-1 byte by using scanl instead of zipWith.

Haskell, 25 bytes
scanl(+)0$(:[-1])=<<[1..]

Try it online!
Constructs an infinite list.

Haskell, 27 bytes
0:0%1
a%d=a+1:a:(a+d)%(d+1)

Try it online!
Haskell, 30 bytes
0:do a<-scanl(+)0[1..];[a+1,a]

Try it online!

Jelly, 6 bytes
HḶS‘_Ḃ

A monadic link accepting (1-indexed) n which returns a(n).
Try it online! Or see the test-suite
How?
HḶS‘_Ḃ - link: n
H      - halve         -> n/2.0
 Ḷ     - lowered range -> [0,1,2,...,floor(n/2.0)-1]
  S    - sum           -> TriangleNumber(floor(n/2.0)-1)
   ‘   - increment     -> TriangleNumber(floor(n/2.0)-1)+1
     Ḃ - bit = 1 if n is odd, 0 if it's even
    _  - subtract      -> TriangleNumber(floor(n/2.0)-1)+isEven(n)

Hm, interesting approach right there.

APL (Dyalog Unicode), 16 12 bytesSBCS
Anonymous tacit prefix function. 0-indexed.
+/⊢↑∘∊¯1,¨⍨⍳

Try it online!
+/ the sum of
⊢↑ the first n elements
∘∊ of the ϵnlisted (flattened)
¯1,¨⍨ negative-one-appended-to-each
⍳ first n ɩndices (0 through n–1

Ah, that was my solution...guess it was similar enough.

05AB1E, 10 bytes
ÎF<NÈi¼¾>+

Try it online!
Explanation
Î             # initialize stack with: 0, input
 F            # for N in [0 ... input-1] do:
  <           # decrement the current number
   NÈi        # if N is even
      ¼       # increment a counter
       ¾>     # push counter+1
         +    # add to current number

Another 10-byter: ÎFNÈN;Ì*<O

ÎGDN+D< generates the sequence, but grabbing the nth element seems... hard in 3 bytes.

PHP, 73 64 55 51 47 bytes
First method
First code golf answer!
I'm sure there's PHP tricks to make it shorter and the maths can probably be improved.
Takes n as the first argument and outputs the nth number in the sequence.
$y=$argv[1]/2;for(;$i<$y+1;)$x+=$i++;echo$x-($y|0);

Minus 9 bytes by removing "$x=0;" and "$i=0".
Minus 9 bytes thanks to @Kevin Cruijssen improving the for loop and loss of the end tag.
Minus 1 byte using bitwise or "|" rather than "(int)"
Minus 3 bytes thanks to @Dennis as you can remove the tags by running it from the command line with "php -r 'code here'"
Try it online!
Second method
Matched my previous answer with a whole new method!
for(;$i<$argv[1];$i++)$x+=($y^=1)?$i/2+1:-1;echo$x;

Using XOR and the tenary operator to switch between sums in the loop.
Edit: This doesn't work for n=0 and I have no idea why. $i isn't assigned so therefore it should be 0, therefore the loop ($i<$argv[1]) should fail as (0<0==false), therefore a non assigned $x should output as 0 and not 1.
Try it online!
Third method
Converting the excel formula @Wernisch created to PHP gives a 47 byte solution
$z=$argv[1];echo(pow($z,2)+(($z&1)?7:-2*$z))/8;

Try it online!

Hi, welcome to PPCG! If you haven't yet, tips for golfing in PHP and tips for golfing in  might be interesting to read through. Some things to golf: you can remove the trailing ?>. Removing $x=0 and $i=0 is indeed allowed (if not, $x=$i=0 would have been shorter as well). Also, the loop can be shortened to for(;$i<$y+1;)$x+=$i++;. Which is -15 bytes in total. Enjoy your stay! :)

@KevinCruijssen thanks very much!

You're welcome. Btw, your TIO is currently still 60 bytes instead of 58. And not sure why you've stated 57. Try it online.

@KevinCruijssen I kept posting the wrong TIO! TIO says 58 now but I've posted 55 as you can remove "php" from the opening tag, just not in TIO

@Wernisch thanks for your formula!

Octave, 32 bytes
@(x)fix((x-~(m=mod(x,2)))^2/8)+m

Try it online!
Outputs the n-th number, 0-indexed. Uses the same formula as several other answers.

Java (JDK 10), 20 bytes
x->x%2+(x=~-x|1)*x/8

Try it online!
Port of TFeld's Python 2 anwser, so go give them an upvote! ;)

R, 35 34 bytes
(u=(n=scan())-n%%2-1)-n+(15+u^2)/8

Try it online!
First output option.Same formula as many other answers (I'd like to point to the first answer providing the formula, I can't figure which it is).
Second and third output options below:
R, 43 bytes
function(m,n=1:m,u=n%%2+1)((n-u)^2-1)/8+2-u

Try it online!
R, 51 bytes
while(T){cat(((T-(u=T%%2+1))^2-1)/8+2-u," ");T=T+1}

Try it online!

Matlab/Octave, 31 26 bytes
5 bytes saved thx to Luis Mendo!
@(n)sum(1:n/2+.5)-fix(n/2)

You can probably use fix instead of floor, and n/2+.5 instead of ceil(n/2)

@LuisMendo Ty! Didn't know about fix() and didn't expect 1:n/2+.5 to work - so many things that could go wrong, but they actually don't :)

R, 35 bytes
diffinv(rbind(n<-1:scan(),-1)[n-1])

Try it online!
I thought this was an interesting alternative to @JayCe's answer since it doesn't port very well to languages without built-in support for matrices, and happens to be just as golfy.
1-indexed, returns the first n elements of the sequence.
How it works:
rbind(n<-1:scan(),-1) constructs the following matrix:
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]   -1   -1   -1   -1

Because R holds matrices in column-major order, if we were to convert this to a vector, we would obtain a vector
1 -1 2 -1 3 -1 4 -1

which if we take a cumulative sum of, we would get
1 0 2 1 4 3 7 6

which is the sequence, just without the leading 0. diffinv fortunately adds the leading zero, so we take the first n-1 values from the matrix and diffinv them, obtaining the first n values of the sequence.

I am a big fan of your 'diffinv' answers.

@JayCe credit to user2390246 for introducing diffinv to me!

Dodos, 69 bytes
	. w
w
	. h
	+ r . ' dab h '
h
	h ' '
	. dab
r

	r dip
.
	dot
'
	dip

Try it online!

Somehow this is the longest answer.
Explanation.
┌────┬─────────────────────────────────────────────────┐
│Name│Function                                         │
├────┼─────────────────────────────────────────────────┤
│.   │Alias for "dot", computes the sum.               │
├────┼─────────────────────────────────────────────────┤
│'   │Alias for "dip".                                 │
├────┼─────────────────────────────────────────────────┤
│r   │Range from 0 to n, reversed.                     │
├────┼─────────────────────────────────────────────────┤
│h   │Halve - return (n mod 2) followed by (n/2) zeros.│
└────┴─────────────────────────────────────────────────┘

QBasic 1.1, 49 bytes
INPUT N
R=1
FOR I=1TO N\2-1
R=R+I
NEXT
?R-N MOD 2

1-indexed.

QBasic 1.1, 30 bytes
INPUT N
?(N-1OR 1)^2\8+N MOD 2

Uses TFeld's algorithm. 0-indexed.

QBasic, 31 bytes
The just-implement-the-spec solution comes in slightly longer than Erik's solution.
DO
?n
i=i+1
n=n+i
?n
n=n-1
LOOP

This outputs indefinitely. For purposes of running it, I recommend changing the last line to something like LOOP WHILE INPUT$(1) <> "q", which will wait for a keypress after every second sequence entry and exit if the key pressed is q.

Japt -x, 6 bytes
Outputs the nth term, 1-indexed.
z oªUv

Try it
z oªUv     :Implicit input of integer U
z          :Floor divide by 2
  o        :Range [0,Uz)
   ª       :Logical OR of each with
    Uv     :Parity of U
           :Implicit output of sum

C# (.NET Core), 56 bytes
n=>{int a=0,i=0;for(;++i<n;)a+=i%2<1?-1:i/2+1;return a;}

-2 bytes thanks to Kevin Crujssen
Try it online!
1 indexed. Returns a(n)
Ungolf'd:
int f(int n)
{
    // a needs to be outside the for loop's scope,
    // and it's golfier to also define i here
    int a = 0, i = 1;
    // basic for loop, no initializer because we already defined i
    for (; ++i < n;)
    {
        if (i%2 < 1) {
            // if i is even, subtract 1
            a -= 1;
        }
        else
        {
            // if i is odd, add (i / 2) + 1
            // this lets us handle X without defining another int
            a += i / 2 + 1;
        }
    }
    // a is the number at index n
    return a;
}

i=1;for(;i<n;i++) can be i=0;for(;++i<n;) and i%2==0 can be i%2<1.

@KevinCruijssen so I can, thanks! I should've seen the 2nd one, but I didn't thnk the first one would work as I thought for loops only checked the conditional after the first loop. TIL

Nope, it checks before the first iteration already. A do-while will check after completing the first iteration. :)

In very rare cases you could even merge an if with a for-loop. For example: if(t>0)for(i=0;i<l;i++) to for(i=0;t>0&i<l;i++). I've almost never been able to use this in my answers, though.

that's pretty awesome, I'll definitely have to keep that in mind next time I do C# golfing, which is quite rare these days :P most of my C# work is decidedly ungolfy

You can remove i and use n directly instead, saving 4 bytes: n=>{int a=0;for(;n-->1;)a+=n%2<1?-1:n/2+1;return a;}

Husk, 11 9 8 bytes
ΘṁṠe→Θ∫N

Saved a byte thanks to H.PWiz.
Outputs as an infinite list.
Try it online!
Explanation
ΘṁṠe→Θ∫N
      ∫N   Cumulative sum of natural numbers (triangular numbers).
     Θ     Prepend 0.
 ṁṠe→      Concatenate [n + 1, n] for each.
Θ          Prepend 0.

Jelly, 6 bytes
Return the first n numbers.
Rj-ÄŻḣ

Try it online!

Very similar to EriktheOutgolfer's answer.

><>, 23 bytes
00v
1->:n9o{1+{{:{+:n9o

I've never done any ><> golfing before, so this can almost certainly be shorter! Is there any way to initialize the stack with two zeros on it?
Try it online!

Brain-Flak, 68 42 bytes
{({}[()]<({}([{}]()))>)}{}({({}[()])}{}{})

Try it online!

JavaScript, 49 48 45 bytes
x=>eval('for(i=0,r=1;++i<x+2;)r+=i%2?-1:i/2')

Try it online!
Not as pretty as @tsh answer, but mine works for bigger numbers.
And now thanks @tsh, for the eval solution !

<=x+1 can be <x+2

x=>eval('for(i=0,r=1;++i<x+2;)r+=i%2?-1:i/2') should be shorter.

Does eval return the last modified value ? I still don't fully understand what it can do.

It return the value of statement (which may be covered in do statement in later version).

Charcoal, 15 bytes
Ｉ∨ΣＥＮ⎇﹪ι²±¹⊕⊘ι⁰

Try it online! 0-indexed. Link is to verbose version of code. The formula would probably be shorter, but what's the fun in that? Explanation:
    Ｎ           Input as a number
   Ｅ            Map over implicit range
     ⎇          Ternary
      ﹪ι²       Current value modulo 2
         ±¹     If true (odd) then -1
           ⊕⊘ι  Otherwise calculate X as i/2+1
  Σ             Take the sum
 ∨            ⁰ If the sum is empty then use zero
Ｉ               Cast to string and implicitly print

Befunge 93, 26 bytes
<v0p030
 >:.130g+:30p+:.1-

Runs indefinitely
Try it online, though output gets a little wonky and goes back down after x=256, presumably TIO can't handle characters above U+256. Works fine at https://www.bedroomlan.org/tools/befunge-playground (Chrome only, unfortunately. With Firefox, endlines get removed at runtime, for some reason...)

Pyth, 8 bytes
s<s,R_1S

Returns nth number in the sequence, 0-indexed. Try it online
Explanation, with example for n=5:
s<s,R_1SQQ   Final 2 Q's are implicit, Q=eval(input())

       SQ    1-indexed range        [1,2,3,4,5]
   ,R_1      Map each to [n,-1]     [[1,-1],[2,-1],[3,-1],[4,-1],[5,-1]]
  s          Sum (Flatten)          [1,-1,2,-1,3,-1,4,-1,5,-1]
 <       Q   Take 1st Q             [1,-1,2,-1,3]
s            Sum, implicit output   4

J, 17 bytes
1#.[{._1,@,.~1+i.

A port of Adám's APL solution.
Try it online!

Stax, 7 bytes
é╛▼¥,▐_

Run and debug it

APL (Dyalog Classic), 9 bytes
+\¯1⌈-\∘⍳

Try it online!
uses ⎕io←1

GMS2, 39 bytes
a=argument0 return a*a/8+(a mod 2?7:a*-2)/8

With GMS1 it takes 43 bytes:
a=argument0 b=a*-2if a mod 2b=7return a*a/8+b/8

Charm, 64 bytes
1 setref [ 1 ] [ 0 getref + put 1 - put 0 [ 1 + ] modref ] while

Try it online!

Convex, 10 9 bytes
_½,ª)\2%-

Try it online!
Based on Jonathan Allan's Jelly approach (which was probably based on OP editing the question with another definition of the sequence). 1-indexed.
Explanation:
_½,ª)\2%- Stack: [A]
_         Duplicate. Stack: [A A]
 ½        Halve. Stack: [A [A]½]
  ,       Range, [0..⌊N⌋). Stack: [A [[A]½],]
   ª      Sum. Stack: [A [[A]½],]ª]
    )     Increment. Stack: [A [[[A]½],]ª])]
     \    Swap. Stack: [[[[A]½],]ª]) A]
      2   2. Stack: [[[[A]½],]ª]) A 2]
       %  Modulo. Stack: [[[[A]½],]ª]) [A 2]%]
        - Minus. Stack: [[[[[A]½],]ª]) [A 2]%]-]

Perl 6,  38  26 bytes
{(0,{$_+(($+^=1)??++$ !!-1)}...*)[$_]}

Try it
{(+^-$_+|1)**2 div 8+$_%2}

Based on reverse engineering TFeld's Python answer.
Try it
Expanded
38 byte (sequence generator):
{  # bare block lambda with implicit parameter $_

  (
    # generate a new sequence everytime this function is called

    0,    # seed the sequence

    {     # bare block that is used to generate the rest of the values

      $_  # parameter to this inner block (previous value)

      +

      (
          # a statement that switches between (0,1) each time it is run
          ( $ +^= 1 )

        ??     # when it is 1 (truish)
          # a statement that increments each time it is run
          ++$ # &prefix:« ++ »( state $foo )

        !!     # or else subtract 1
          -1
      )
    }

    ...  # keep generating until:

    *    # never stop

  )[ $_ ] # index into the sequence
}

Note that this has the benefit that you can pass in * to get the entire sequence, or pass in a Range to more efficiently generate multiple values.
26 byte (direct calculation):
{  # bare block lambda with implicit parameter $_

  (

    +^     # numeric binary negate
      -$_  # negative of the input
      +|   # numeric binary or
      1

  ) ** 2   # to the power of 2

  div 8     # integer divide it by 8

  + $_ % 2  # add one if it is odd
}

05AB1E, 8 bytes
;L¨O>¹É-

Try it online!
Based on Jonathan Allan's Jelly approach (which was probably based on OP editing the question with another definition of the sequence), so 1-indexed.

+1. I had a similar approach prepared in 05AB1E which I planned to post in a few days if no-one else posted one. It's slightly different (I first decrease the halve before creating the list, instead of removing the tail; and I use I instead of ¹), but the general approach and byte-count is exactly the same: ;<LO>IÉ-

@KevinCruijssen Would've posted yesterday if I had the ability to think more deeply, but, well, this is finals period, thinking too deeply about this is forbidden. :P

Ah, I'm glad I don't have finals anymore. I am pretty busy at work as well though, and have to postpone code-golf sometimes more often than I would like. ;p Good luck with your exams!

Oasis, 7 bytes
>vLSnv-

Try it online!

Sequential solution
Oasis, 12 bytes
bn>v>n2%*<+0

Try it online!

Ruby, 21 bytes
A straight port of TFeld's answer also works in Ruby:
->n{(~-n|1)**2/8+n%2}

Try it online!

Common Lisp, 75 bytes
(defun f(n)(+(/((lambda(x)(*(- x 1)x))(+(floor n 2)(mod n 2)))2)(mod n 2)))

Try it online!
Not the best.  I'm still learning Lisp.


text:
New Password Idea: Word-walker
I thought of a new way to generate my passwords, and even though it's probably not very clever in the long run, it could still make for a fun code-golf.
Taking a string of words, the password is generated thus:

Pick the nth character in the nth word
If n is larger than the word, continue counting backwards

Example:
This is a fun task!
T     s a  u      !

T is the first character
s is the second
a is the first, but going back and forth it is also the third
u is the second but because of counting backwards it's also the fourth
'!' is the fifth character in 'task!' and thus will be included in the final password, Tsau!
Rules

Input will be a string
Separate the string on spaces, all other characters must be included
Uppercase letters must remain uppercase, same with lowercase
You take n steps in each word, where n is the number of words that have come before plus one
If n is larger than the word, you must step backwards through the word, if you hit the start, you go forward again until you have stepped n times
The first and last character is only stepped once, so 'fun' on the seventh position as an example goes 'funufun' and ends on n, not 'funnuff' and ends on f
Output must be a string

Examples:
Input              Output
Once Upon A Time   OpAe
There was a man    Taaa
Who made a task    Waak
That was neat!     Taa
This is a long string to display how the generator is supposed to work  Tsagnoyotoipto

The shortest code in bytes wins!

to is the 12th word (0-indexed) in the long string, and therefore the code letter should be t, not o.

@Neil the sequence is 1-indexed, otherwise you can't start with the first letter on the first word (I tried) my bad, I see it now

Tsau! is chinese for Fuck!

Statistically, this is pretty much the same letter frequency as normal English text.  A and I would be over-represented because of single character words "a" and "I"

Also your stepping plan for choosing funufun over funnuff will increase the percentage of vowels in the output.   Cryptographically, this is not a strong password generator.

@Criggie I never intended to use it, but as I said, it would make for a fun challenge, and it appears that the golfers agree

@sergiol Ok, that certainly wasn't intended, but quite funny!

Python 2, 72 bytes
lambda s:''.join((-~i*(w+w[-2:0:-1]))[i]for i,w in enumerate(s.split()))

Try it online!

05AB1E, 11 bytes
#vyN©Fû}®è?

Try it online!
Explanation
#             # split input on spaces
 vy           # for each word in input
   N©F        # N times do, where N is the current iteration
      û}      # palendromize the word
        ®è    # use N to index into the resulting word
          ?   # print

9 bytes in the new version

Java 10, 148 117 114 110 bytes
s->{int i=-1,j;for(var a:s.split(" "))System.out.print(a.charAt((j=a.length()-1)>0*i++?i/j%2<1?i%j:j-i%j:0));}

-31 bytes thanks to @SamYonnou by creating a port of @user71546's JavaScript answer.
-4 bytes thanks to @SamYonnou again, optimizing the algorithm for Java.
Try it online.
Explanation:
s->{                            // Method with String parameter and no return-type
  int i=-1,                     // Step integer, starting at -1
      j;                        // Temp integer
  for(var a:s.split(" "))       // Loop over the parts split by spaces
    System.out.print(           // Print:
     a.charAt((j=a.length()-1)  //  Set `j` to the the length of the part minus 1
               >0               //  If the length of the part is larger than 1 (`j` > 0)
                 *i++?          //  (and increase `i` by 1 in the process with `i++`)
                i/j%2<1?        //   If `i` integer-divided by `j` is even:
                 i%j            //    Print the character at index `i` modulo-`j`
                :               //   Else:
                 j-i%j          //    Print the character at index `j` minus `i` modulo-`j`
               :                //  Else:
                0));}           //   Print the first (and only) character
                                //   (the >0 check is added to prevent divided-by-0 errors)

Doesn't work for test cases  0, 2 and 5

golfed down to 117 "using a more arithmetic approach" similar to what user71546's version seems to be doing: s->{int i=-1,j;for(var a:s.split(" ")){System.out.print(a.charAt(++i>(j=a.length()-1)?j>0?i/j%2==0?i%j:j-i%j:0:i));}}

@SamYonnou Thanks! And I've been able to golf three more bytes by removing the brackets and changing ==0 to <1.

golfed to 110 by getting rid of the ++i>(j=a.length()-1) condition since the math works the same way regardless of the result of that condition: s->{int i=-1,j;for(var a:s.split(" "))System.out.print(a.charAt(0<(j=a.length()+i-++i)?i/j%2<1?i%j:j-i%j:0));}

@SamYonnou Thanks again! I've slightly changed 0<(j=a.length()+i-++i)? to (j=a.length()-1)>0*i++? so the explanation was a bit easier to type (no bytes saved doing so however).

Jelly, 12 bytes
ḲJị"ŒBṖȯ$€$Ɗ

Try it online!

Charcoal, 16 bytes
⭆⪪Ｓ §⁺ι✂ι±²¦⁰±¹κ

Try it online! Link is to verbose version of code. Explanation:
  Ｓ                 Input string
 ⪪                  Split on spaces
⭆                   Map over words and join
      ι ι           Current word
       ✂ ±²¦⁰±¹     Slice backwards from 2nd last character to start exclusive
     ⁺              Concatenate
    §          κ    Cyclically index on current word index
                    Implicitly print

I don't often get to use Slice's last parameter.

I like that Charcoal uses a scissors glyph

JavaScript (Node.js), 78 70 69 68 bytes
-1 byte @Arnauld
x=>x.split` `.map((y,i)=>y[a=i%(l=y.length-1)|0,i/l&1?l-a:a]).join``

Try it online!
Explanation

x=>
 x.split` `                    // Split the words by spaces
 .map((y,i)=>                  // For each word:
  y[                           //  Get the character at index:
                               //   A walk has cycle of length (2 * y.length - 2)
   a=i%(l=y.length-1)|0,       //   Calculate index a = i % (y.length - 1)
   i/l&1                       //   Check in which half the index i in
   ?l-a                        //   If in the second half of cycle, use y.length - 1 - a
   :a                          //   If in the first half of cycle, use a
  ]
 ).join``                      // Join back the letters

Stax, 9 bytes
éñ~╗D¡┤Gq

Run and debug it
Unpacked, ungolfed, and commented, it looks like this.
j       split into words
{       start block for mapping
  cDrD  copy word; remove first and last character; reverse
  +     concatenate with original word
  i@    modularly (wrap-around) index using map iteration index
m       perform map

Run this one

Red, 135 bytes
func[s][n: 0 p: copy""foreach w split s" "[append/dup r: copy""append w
reverse copy/part next w back tail w n: n + 1 append p r/(n)]p]

Try it online!
Readable:
f: func[s][
    n: 0
    p: copy ""
    foreach w split s "  "[
        r: copy ""
        append/dup r append w reverse copy/part next w back tail w n: n + 1
        append p r/(n)
    ]
    p
]

k, 31 30 28 bytes
{x{*|y#x,1_|1_x}'1+!#x}@" "\

Try it online!

|-1_ -> 1_|

you can save 2 bytes by swapping the inner lambda's arguments

Perl 5, 76 bytes
print map{$l=length;substr$_.reverse,$i++%(2*$l-2||1)*(1+1/$l),1}split" ",<>

Try it online!

Husk, 14 11 bytes
SzS!ö!…¢ŀŀw

Try it online! Inspiration was taken from this program by Zgarb for the forward-and-reverse stepping.

Japt, -P, 11 bytes
¸Ëê ÅªD gEÉ

Try it
¸Ë+s1J w)gE

Try it

Explanations
¸Ëê ÅªD gEÉ
¸               :Split on spaces
 Ë              :Map over each element D at index E
  ê             :  Palindromise
    Å           :  Slice off the first character
     ªD         :  Logical OR with the original element (the above will return an empty string for single character words)
        g       :  Get the character at index
         EÉ     :  E-1

¸Ë+s1J w)gE
¸               :Split on spaces
 Ë              :Map over each element D at index E
   s1J          :  Slice off the first and last characters
       w        :  Reverse
  +     )       :  Append to D
         gE     :  Get the character at index E

Haskell, 65 62 61 bytes
zipWith(\i->(!!i).cycle.(id<>reverse.drop 1.init))[0..].words

Try it online!
It requires the latest version of Prelude which features the <> function.
                   words    -- split the input string into a list of words
zipWith(\i->     )[0..]     -- zip the elements i of [0..] and the words pairwise
                            -- with the function
      ... <> ...            --   call the functions with a word and concatenate
                            --   the results. The functions are
        id                  --     id: do nothing
        reverse.drop 1.init --     drop last and first element and reverse
    cycle                   --   repeat infinitely
(!!i)                       -- take the ith elemnt of

Edit: -3 bytes thanks to @user28667, -1 byte thanks to @B. Mehta

Looks like zipWith(\i w->(cycle$id<>reverse.drop 1.init$w)!!i)[0..].words also works.

You can save another byte by changing the lambda to \i->(!!i).cycle.(id<>reverse.drop 1.init) factoring out the explicit w mention (TIO)

PHP, 77 bytes
while(ord($w=$argv[++$i]))echo($w.=strrev(substr($w,1,-1)))[~-$i%strlen($w)];

Try it online!

-3 bytes thanks to Kevin
-10 bytes thanks to Titus

Nice answer! One small thing to golf: you can get rid of the brackets and one additional third byte by changing foreach(...){$c=...;echo$c[...];} to foreach(...)echo($c=...)[...];. Try it online: 87 bytes

You can use the argument list to automatically split to words (-8 bytes), and .= saves two bytes: while(ord($w=$argv[++$i]))echo($w.=strrev(substr($w,1,-1)))[~-$i%strlen($w)]; try it online

Nice! One question: ~-$i does the same as ($i-1), right?

Pyth, 12 bytes
s.e@+b_Ptbkc

Try it online
s.e@+b_PtbkcQ   Final Q (input) implicit

           cQ   Split on spaces
 .e             Map the above with b=element, k=index
       Ptb        Remove 1st and last character
      _           Reverse
    +b            Prepend the unaltered element ('abcd' -> 'abcdcb')
   @      k       Get the kth character (0 indexed, wrapping)
s               Join on empty string, implicit output

C (gcc), 148 bytes (string version), 114 bytes (print version)
If I must return a string (long version):
char c[99]={0};char*f(s,t,u,i,j,k)char*s,*t,*u;{for(u=c,i=0;t=strtok(s," ");s=0,i++)*u++=t[j=strlen(t),k=2*j-(j>1)-1,(i%k<j?i%k:k-i%k)%j];return c;}

Try it online!
Otherwise, I just print and don't worry about a buffer (short version):
f(s,t,i,j,k)char*s,*t;{for(i=0;t=strtok(s," ");s=0,i++)putchar(t[j=strlen(t),k=2*j-(j>1)-1,(i%k<j?i%k:k-i%k)%j]);}

Try it online!

-(j>1)-1 can be replaced by +~(j>1) with 1 byte less I think.

106 chars: putchar( t[ j=strlen(t)-1, k = i++ % (j ? j*2 : 1), k<j ? k : j+j-k ]); Try it online!

Buffered version: Global variables are implicitly zeroed. Replace *u++ with c[i] and remove u.

Building on @user5329483 105 bytes

Building on @ceilingcat 103 bytes

AWK, 79 bytes
Mostly because I'm curious to see any better awk or bash solutions!
{for(i=1;i<=NF;i++){l=length($i);k=int(i/l)%2?l-i%l:k%l;printf substr($i,k,1)}}

Try it online!

C# (.NET Core), 111 bytes
s=>{int i=-1,j;return String.Concat(s.Split(' ').Select(a=>a[++i>(j=a.Length-1)?j>0?i/j%2<1?i%j:j-i%j:0:i]));};

Try it online!

Welcome to PPCG. Nice answer

Vyxal, 11 bytes
⌈₅(ʁ):ẏ¨£i∑

Try it Online!
⌈           # Input split on spaces
 ₅( )       # repeat len(that) times...
   ʁ        # Palindromise each word
       ¨£   # Zipping...
     :      # Words
      ẏ     # range(0, len(words))
         i  # Index the numbers into the words
          ∑ # Stringify

10: ⌈₅(ʁ)¨2i;∑ (8 with s flag)

Powershell 208 186 170 bytes
$args|%{$i=0;-join($_.Split()|%{$l=($b=($a=$_)).Length;if($l-gt2){$b=($a|%{-join$a[($l-2)..1]})}for($j=0;$a.Length-le$i;$j++){$a+=($b,$_)[$j%2]}$a.Substring($i,1);$i++})}

Ungolfed:
$args|%{
   $i=0;
    -join($_.Split()|%{
        $l=($b=($a=$_)).Length;
        if($l-gt2){
            $b=($a|%{-join$a[($l-2)..1]})
        }
        for($j=0;$a.Length-le$i;$j++){
            $a+=($b,$_)[$j%2]
        }
        $a.Substring($i,1);
        $i++
    })
}

Test cases below or try it online
@(
    "This is a fun task!",
    "Once Upon A Time",
    "There was a man",
    "Who made a task",
    "That was neat",
    "This is a long string to display how the generator is supposed to work"
)|%{$i=0;-join($_.Split()|%{$l=($b=($a=$_)).Length;if($l-gt2){$b=($a|%{-join$a[($l-2)..1]})}for($j=0;$a.Length-le$i;$j++){$a+=($b,$_)[$j%2]}$a.Substring($i,1);$i++})}

There's a lot you could make shorter here. Have you see the tips for golfing in PowerShell?

Thanks! I’d thought about using switch just after posting, but the rest hadn’t occurred to me yet.

Also one actual problem here is that you don't really take input anywhere in this snippet. We're pretty flexible about being able to write a program or function, but yours has implicit input. As a first step you might simply replace your ""|%{ with $args|%{, but I think you can golf it more effectively too ;)

Here's a demonstration in TIO that also shows how to use the arguments feature for test cases. Keeping the code block for your code only also let's you use TIO's easy linking and byte counts for your post!

J, 43 bytes
[:(>{~"_1#@>|i.@#)[:(,}.@}:)&.>[:<;._1' '&,

ungolfed
[: (> {~"_1 #@> | i.@#) [: (, }.@}:)&.> [: <;._1 ' '&,

<;._1 ' '&, split on spaces
(, }.@}:)&.> for each word, kill the first and last elm and append to word
#@> | i.@# take the remainder of each word's length divided into its index
> {~"_1 take that result and pluck it from each word.

Try it online!

CJam, 22 bytes
qS/{_);1>W%+T_):T@*=}%

Try it online!

Ruby -pl, 60 bytes
gsub(/(\S+) ?/){w=$1+$1.reverse[1..-2]
w[(-2+$.+=1)%w.size]}

Attempt This Online!