9
\$\begingroup\$

Task:

Given sample index, x, calculate sample value f(x) of triangular wave, with period of 4 samples and amplitude 1. Offset can be negative and sample value could be either {0, 1, -1}.

Test cases:

   -5 -> -1
   -4 -> 0
   -3 -> 1
   -2 -> 0
   -1 -> -1
    0 -> 0
    1 -> 1
    2 -> 0
    3 -> -1
    4 -> 0
    5 -> 1

Personally I know two approaches in C - the first is using lookup table, the second is using conditional instructions. For brownie points, could you impress me with a pure "math" approach? (I mean a pure functional approach, e.g. not using conditional instructions or using memory for LUT.) But this is not an restriction. If you can't, or your language does not support it - just post any solution

\$\endgroup\$
6
  • 3
    \$\begingroup\$ What do you mean by "offset can be negative"? Also this is basically just a trigonometric function, so I'd be surprised if it isn't a dupe of something. \$\endgroup\$ May 16, 2017 at 1:08
  • \$\begingroup\$ @JungHwanMin This has much more relaxed rules, so it's not really a dupe (though it asks for the same thing). \$\endgroup\$
    – user45941
    May 16, 2017 at 1:09
  • \$\begingroup\$ @Mego alright. Retracting my vote. \$\endgroup\$ May 16, 2017 at 1:10
  • \$\begingroup\$ Related: codegolf.stackexchange.com/q/5522/60043 \$\endgroup\$ May 16, 2017 at 1:13
  • \$\begingroup\$ Can the wave be out of phase relative to the example? \$\endgroup\$
    – Maria
    May 16, 2017 at 17:45

22 Answers 22

12
\$\begingroup\$

Mathematica, 8 bytes

Im[I^#]&

Explanation

Im[I^#]&
   I^#    (* Raise the imaginary unit to the input power *)
Im[   ]   (* Take the imaginary part *)
\$\endgroup\$
2
  • 3
    \$\begingroup\$ Ohh, beautiful approach. How did I not see this? :D \$\endgroup\$
    – hyper-neutrino
    May 16, 2017 at 1:19
  • \$\begingroup\$ cant see algo how to generate imaginary unit in C.. =( im assembler man ^^ using builtins in exotic languages is not in my favor ) however is an answer.. \$\endgroup\$
    – user69099
    May 17, 2017 at 23:54
7
\$\begingroup\$

TI-Basic, 7 5 4 bytes

sin(90Ans

(Degree mode) -1 byte from @immibis from my old answer.


Old answer

imag(i^Ans

Pure-math approach on a calculator. :)

Just for fun, here's another pure-math (ish) solution for 9 bytes (In radian mode), or 8 bytes (Degree mode)

2/πsin-1sin(πAns/2 # Radians
90-1sin-1sin(90Ans # Degrees
\$\endgroup\$
4
  • \$\begingroup\$ yeah, but you just forget an imag() implementation.. but usin others code is fine, though.. good answer :) \$\endgroup\$
    – user69099
    May 18, 2017 at 0:03
  • 2
    \$\begingroup\$ @xakepp35 I don't understand. imag() is a valid function on TI-BASIC. \$\endgroup\$ May 18, 2017 at 13:52
  • \$\begingroup\$ What's wrong with sin(90Ans? Why do you need the extra 90-1sin-1? \$\endgroup\$
    – user253751
    May 19, 2017 at 0:47
  • \$\begingroup\$ @immibis The 90^-1sin^-1 makes it a triangle wave for all values, but sin(90Ans works for what the question asks. \$\endgroup\$ May 19, 2017 at 3:46
6
\$\begingroup\$

Python 2, 20 bytes

lambda n:n%2-n%4/3*2

Try it online!

I'm running a brute-force search for shorter arithmetic or bitwise expressions, I'll see if anything turns up. This one I hand-found.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Brute force expression search? Nice! \$\endgroup\$
    – Graviton
    May 16, 2017 at 2:31
5
\$\begingroup\$

Julia 0.5, 12 bytes

!n=(2-n&3)%2

I like this approach because it's unlikely to be the shortest in any other language.

Try it online!

How it works

Julia's operator precedence is a bit unusual: unlike most other languages, bitwise operators have the same precedence as their arithmetic counterparts, so & (bitwise multiplication) has the same precedence as *.

First, n&3 takes the input modulo 4, with positive sign.

The result – 0, 1, 2, or 3 – is then subtracted from 2, yielding 2, 1, 0, or -1.

Finally, we take the signed remainder of the division by 2, returning 0, 1, 0, or -1.

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

Jelly, 3 bytes

ı*Ċ

Try it online!

How it works

ı*Ċ  Main link. Argument: n

ı*   Elevate i, the imaginary unit, to the n-th power.
  Ċ  Take the imaginary part of the result.
\$\endgroup\$
4
\$\begingroup\$

dc, 13

Not sure if you count the modulo % operator as "pure math":

?1+d*v4%1-2%p

Try it online. Note that dc uses _ instead of - to indicate negative numbers.

Explanation

?              # read input
 1+            # add 1
   d*v         # duplicate, multiply, square root (poor-mans abs())
      4%       # mod 4
        1-     # subtract 1
          2%   # mod 2
            p  # print

Note that dc's % mod operator is the standard "CPU" version that maps negative values to negative values.

\$\endgroup\$
1
  • \$\begingroup\$ Can you just do abs((x+1)%4)-1 instead? \$\endgroup\$ May 16, 2017 at 18:02
2
\$\begingroup\$

brainfuck, 136 bytes

>,>++++<[>->+<[>]>[<+>-]<<[<]>-]>>>>-[>+<-----]>--[-<+>>>+>>>+>>>+<<<<<<<<]<->>>>>>->--[>+<++++++]>++<<<<<<<<<<[[->>>+<<<]>>>-]>[.[-]]>.

Try it online!

There's probably a more trivial answer, but this essentially uses a table of values. Although brainfuck takes input as ASCII characters with positive values from 0 to 127, it still works as if it were able to accept negative values (to test, replace the , with n amount of - characters).

How it works

>,                                   take input (X)
>++++<                               take second input for modulo (4)
[>->+<[>]>[<+>-]<<[<]>-]             calculate X mod 4
>>>>-[>+<-----]>--                   create initial '1' character
[-<+>>>+>>>+>>>+<<<<<<<<]            duplicate '1' four times as 1,1,1,1
<->>>>>>->--[>+<++++++]>++<<<<<<<<<< change 1,1,1,1 to 0,1,0,-1 
[[->>>+<<<]>>>-]>[.[-]]>.            move to the right X%4 * 3 times, then print the following two characters ( 0, 1, 0,-1)
\$\endgroup\$
1
\$\begingroup\$

Python, 26 24 21 bytes

lambda x:(1j**x).imag

-2 bytes thanks to ValueInk for realizing that the mathematical method is actually longer than the trivial approach :P
-3 bytes thanks to Dennis for pointing out that I don't need the int(...), thus making this shorter :)

\$\endgroup\$
6
  • \$\begingroup\$ lambda x:[0,1,0,-1][x%4] is actually shorter than your int-coerced answer lol \$\endgroup\$
    – Value Ink
    May 16, 2017 at 1:44
  • \$\begingroup\$ @ValueInk Oh...um this is embarrasing lol \$\endgroup\$
    – hyper-neutrino
    May 16, 2017 at 1:52
  • 2
    \$\begingroup\$ Why would you use int() in the first place though? \$\endgroup\$
    – Dennis
    May 16, 2017 at 1:59
  • \$\begingroup\$ @Dennis Because .imag gives a floating-point value and I'm not sure if that's allowed by the specs. It doesn't matter now :) \$\endgroup\$
    – hyper-neutrino
    May 16, 2017 at 2:19
  • \$\begingroup\$ If floats aren't allowed, JavaScript will not be able to compete. \$\endgroup\$
    – Dennis
    May 16, 2017 at 2:28
1
\$\begingroup\$

Python, 20 bytes

lambda n:n%2*(2-n%4)

An unnamed function which returns the result.

Try it online!

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

Mathematica, 18 bytes

#~JacobiSymbol~46&
\$\endgroup\$
3
  • 5
    \$\begingroup\$ This doesn't quite work: inputs 9 and 11 both give 1 as output, for example. The period of this function is 184, not 4. \$\endgroup\$ May 16, 2017 at 4:22
  • 1
    \$\begingroup\$ However, JacobiSymbol[-4,#]& does work, and just costs one more byte. Nice idea! \$\endgroup\$ May 16, 2017 at 6:15
  • \$\begingroup\$ again cant see an algrithm( just builtines written by others and couple of short code.. ah, all as usual. fine answer though \$\endgroup\$
    – user69099
    May 17, 2017 at 23:56
1
\$\begingroup\$

Pari/GP, 12 bytes

n->imag(I^n)

Try it online!

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

PHP, 20 bytes

<?=2<=>($argn&3?:2);
\$\endgroup\$
1
\$\begingroup\$

Haskell, 19 bytes

Port of Dennis's Julia solution, just because he said it wouldn't be shortest in any other language. (Someone might still prove me wrong that it's shortest in Haskell.)

f n=rem(2-n`mod`4)2

Try it online!

Haskell has two different remainder functions, one (rem) works like the Julia one, while the other (mod) gives a positive result even when the first argument is negative, and so is suitable for translating &3. (Haskell's actual &, called .&., alas requires an import Data.Bits.)

\$\endgroup\$
1
  • \$\begingroup\$ As far as I can tell, a port of Dennis's Julia solution is optimal for JavaScript too (14 bytes). Shows that even Dennis is fallible! \$\endgroup\$
    – Neil
    May 16, 2017 at 22:02
1
\$\begingroup\$

Octave, 22 bytes

@(x)round(sin(x*pi/2))

Try it online!

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

Ruby, 20 bytes

Simple and clean.

->x{[0,1,0,-1][x%4]}
\$\endgroup\$
0
\$\begingroup\$

C99, 27 bytes

Assuming you want the wave to be centered at the origin:

f(n){return cpow(1i,n)/1i;}

otherwise f(n){return cpow(1i,n);} will do. I originally had a cimag in there, but apparently trying to return an int from a _Complex int yields the real part, so I used that. It makes sense, but it'snnothing I would have predicted. Behavior is the same in gcc and clang

\$\endgroup\$
4
  • \$\begingroup\$ cpow is undefined xD \$\endgroup\$
    – user69099
    May 17, 2017 at 23:59
  • \$\begingroup\$ some #includes omitted, does not compile))))) \$\endgroup\$
    – user69099
    May 18, 2017 at 0:00
  • \$\begingroup\$ but +1 just for C \$\endgroup\$
    – user69099
    May 18, 2017 at 0:00
  • 1
    \$\begingroup\$ @xakepp35 That's actually not the fault of the includes, it's a linker problem. Compile with -std=c99 -lm and it should work. It works fine for me with both gcc and clang without any includes. Well, by fine I mean there are no errors, but a large number of warnings. \$\endgroup\$
    – algmyr
    May 18, 2017 at 0:06
0
\$\begingroup\$

05AB1E, 5 bytes

4%<Ä<

Try it online!


The output is reversed, but from what I understood this is allowed:

+1 byte to multiply output by -1 using (.

   -5 -> 1
   -4 -> 0
   -3 -> -1
   -2 -> 0
   -1 -> 1
    0 -> 0
    1 -> -1
    2 -> 0
    3 -> 1
    4 -> 0
    5 -> -1

4%    # Amplitude of 4...
  <   # Period of 1...
   Ä  # Absolute value...
    < # Period of 1 centered at 0...
\$\endgroup\$
3
  • \$\begingroup\$ what I understood this is allowed \$\endgroup\$
    – user69099
    May 18, 2017 at 0:03
  • \$\begingroup\$ test cases are not passed ;-) \$\endgroup\$
    – user69099
    May 18, 2017 at 0:04
  • \$\begingroup\$ but +1 nice try \$\endgroup\$
    – user69099
    May 18, 2017 at 0:04
0
\$\begingroup\$

Pyth - 7 bytes (possibly 6)

ta2%tQ4

Try it

If the phase of the wave isn't important, 6 bytes:

ta2%Q4

Try it

Explanation:

ta2%tQ4
     Q    # The input
    t     # Subtract 1 to get the phase right (might not be necessary)
   %  4   # Take mod 4
 a2       # Absolute value of the result - 2
t         # Subtract 1 so the result is in [-1,0,1]
\$\endgroup\$
0
\$\begingroup\$

AWK, 26 bytes

{$0=(sqrt(($0%4)^2)-2)%2}1

Try it online!

This is an alternate approach using trig functions without the modulus operator.

{$0=int(sin($0*atan2(0,-1)/2))}1

Try it online !

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

Javascript ES6, 18 17 bytes

n=>n&1&&(++n&2)-1

Firstly, check if the input is even or odd and return 0 for all even values. For all odd inputs, increment and bitwise with 0b10 to remove any bits that don't interest us, then return the answer with an offset.

const f = n=>n&1&&(++n&2)-1;

for (let i = -5; i < 6; i++) {
  document.body.appendChild(document.createElement('pre')).innerHTML = `f(${i}) => ${f(i)}`;
}

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Save a byte by replacing ? :0 with && \$\endgroup\$ May 16, 2017 at 22:28
  • \$\begingroup\$ @SteveBennett Thanks, great idea! \$\endgroup\$
    – Etheryte
    May 17, 2017 at 0:50
0
\$\begingroup\$

JavaScript, 15 bytes

n=>n&3&&2-(n&3)

Bitwise and 3 is equivalent to modulo 4 except without the weird rule on JavaScript's modulos of negative numbers. I did polynomial regression on the first four points at first but then realized I was being dumb because (1, 1), (2, 0), and (3, -1) is just 2-n.

a=n=>n&1&&2-(n&3);
console.log([a(-5), a(-4), a(-3), a(-2), a(-1), a(0), a(1), a(2), a(3), a(4), a(5)])

\$\endgroup\$
1
  • \$\begingroup\$ very well! +1 for the answer \$\endgroup\$
    – user69099
    May 18, 2017 at 0:05
0
\$\begingroup\$

R, 19 bytes

function(n)Im(1i^n)

Try it online!

A port of JungHwan Min's Mathematica answer.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy