27
\$\begingroup\$

Ruby has a strange operator, .., called flip-flop (not to be confused with the range operator, which looks the same). Used in a loop, flip-flop takes two conditions as operands and will return false until the first operand is truthy, then return true until the second operand is truthy, whereupon it returns true one more time and restarts the cycle with false.

0.upto 10 do |i|
  if (i==2)..(i==8)
    puts i
  end
end

# Prints 2, 3, 4, 5, 6, 7, and 8

Attempt This Online

Your task is to implement a higher-order function (or something equivalent in your language) that behaves like flip-flop. It must take two predicate functions as arguments and return a new function that takes an argument and returns falsey until the first predicate returns true given the argument, continues to return true until the second predicate returns true, whereupon the flip-flop returns true one more time (think of it like an inclusive range) and thereafter returns false, until the first predicate returns true again and so on.

Below is an example of such a function called make_flip_flop, which takes two predicate lambdas and returns a new lambda, flip_flop, to be used in the following loop.

flip_flop = make_flip_flop(->i{ i==2 }, ->{ i == 8 })

0.upto 10 do |i|
  if flip_flop.(i)
    puts i
  end
end

# Prints 2, 3, 4, 5, 6, 7, and 8

Here's another example with a different set of predicates:

flip_flop = make_flip_flop(->i{ i % 5 == 0 }, ->i{ i % 5 == 2 })

0.upto 10 do |i|
  if flip_flop.(i)
    puts i
  end
end

# Prints 0, 1, 2, 5, 6, 7, and 10

Rules

  • Please include a brief example or description of how your solution works.

  • Since not all languages have first-class functions, the definition of "predicate" is loose. You could take the names of previously-defined functions to be called or a string to be eval'd, for example. Your solution may not, however, just take primitive values like true and false. It must be your language’s equivalent of a higher-order function.

  • Your predicate functions should take at least one argument, of any type that's convenient, as long as it's reasonable. (A predicate that only takes the specific value 1 is not reasonable, for example.)

  • Built-ins are allowed, but only if they fit the spec (it must be a function or similar, etc.). You can’t post Ruby, 2 bytes, ...

  • Default I/O rules apply, standard rules apply, and standard loopholes are forbidden.

  • This is code golf. Shortest answer in bytes wins.

\$\endgroup\$
7
  • \$\begingroup\$ Sandbox. \$\endgroup\$
    – Jordan
    Commented Oct 14, 2022 at 14:24
  • \$\begingroup\$ I notice that Ruby's 2-byte .. operator wouldn't even fit the spec, even if converted to a conventional prefix function, since it appears to take two expressions evaluated as truthy/falsy as operands, rather than two functions and a single value... \$\endgroup\$ Commented Oct 15, 2022 at 8:51
  • \$\begingroup\$ @DominicvanEssen It’s true. I couldn’t resist making this an FP challenge. \$\endgroup\$
    – Jordan
    Commented Oct 15, 2022 at 12:25
  • 1
    \$\begingroup\$ @Adám Unless I’m misunderstanding you I think the text is correct. When the flip-flop has been returning true and gets “flipped” by the second operand, it returns true once before it starts returning false. It sounds weird but makes sense in the context of matching an inclusive range of lines in a text file, which is its conventional use. \$\endgroup\$
    – Jordan
    Commented Oct 19, 2022 at 14:21
  • 1
    \$\begingroup\$ Consider an edge case where both predicates are identical, say (i==2)..(i==2). In the original Ruby variant, this fires true once, as it corresponds to a 1-element range 2..2. But many current answers that rely on xor operation would fail this test. \$\endgroup\$
    – Kirill L.
    Commented Oct 25, 2022 at 8:02

18 Answers 18

8
\$\begingroup\$

JavaScript (ES6), 26 bytes

Expects [ first_predicate, second_predicate ], where both predicates are functions taking a single parameter.

Returns a flip-flop function which itself returns either 0 or 1.

(p,k=0)=>v=>k|(k^=p[k](v))

Try it online!

Commented

(                  // flip-flop generator taking:
  p,               //   p[] = pair of predicate functions
  k = 0            //   k   = flip-flop status, initialized to 0
) =>               //
  v =>             // anonymous function taking a parameter v
    k | (          //   always return 1 if k is already set
                   //   (because we must still return 1 when the 2nd
                   //   predicate is triggered)
      k ^= p[k](v) //   toggle k if the result of p[k](v) is true
    )              //
\$\endgroup\$
6
\$\begingroup\$

Python, 59 bytes

lambda a,b:lambda x,t={0}:t.add((o:=t.pop()|a(x))>b(x))or o

Attempt This Online!

Anonymous function returning an anonymous function that keeps state in a mutable initialiser.

\$\endgroup\$
2
  • \$\begingroup\$ Ah, so the default value in the inner lambda is per-outer lambda? Nice! \$\endgroup\$
    – Neil
    Commented Oct 14, 2022 at 19:57
  • \$\begingroup\$ @Neil. Pretty sure the entire inner lambda is per outer lambda: The inner function definition is executed each time the outer lambda is called and creates a new function object with its own closure and default values. \$\endgroup\$
    – loopy walt
    Commented Oct 14, 2022 at 20:38
5
\$\begingroup\$

Raku, 18 bytes

->\f,\g{&{f ff g}}

Try it online!

Raku has a built-in operator ff that does exactly what's asked for. My answer is mostly just setting up the functional plumbing around it.

  • -> \f, \g { ... } is an anonymous subroutine taking two arguments.
  • &{ ... } is the anonymous subroutine the top-level subroutine returns. Not having an explicit signature, it takes its argument in the topic variable $_, which the flip-flop operator implicitly checks against.
  • f ff g returns false until the topic variable smartmatches against f, that is, $_ ~~ f, then keeps returning true until $_ ~~ g. Since f and g are functions, those smartmatches are equivalent to f($_) and g($_).
\$\endgroup\$
0
5
\$\begingroup\$

C (clang), 43 bytes

Reusable form as proposed by AZTECCO

#define f(x,a,b)static m;m|(m^=m?x b:x a)&&

Try it online!

C (clang), 41 40 bytes

-1 byte thanks to ceilingcat!

t;f(a(),b(),i,*r){*r=t|(t^=(t?b:a)(i));}

Try it online!

\$\endgroup\$
6
  • 1
    \$\begingroup\$ A perfect example to demonstrate why implicit int is bad. :) \$\endgroup\$
    – corvus_192
    Commented Oct 15, 2022 at 14:43
  • \$\begingroup\$ I don't think this is valid answer, f isn't reusable since t isn't initialized prior usage, moreover I honestly don't really like how the function, variables and for loop mix up, however there's not much you can do in c to achieve the task \$\endgroup\$
    – AZTECCO
    Commented Oct 15, 2022 at 21:06
  • \$\begingroup\$ yeah, I had the same discussion with @solid.py. I guess this answer is a bit of a flop :-) \$\endgroup\$
    – jdt
    Commented Oct 15, 2022 at 21:29
  • \$\begingroup\$ Maybe a bit stretchy but can be valuable. Obviously the t thing has to be addressed in some ways.. Maybe cut it off and just use r pre-initialized, Idk if it would be valid but seems reasonable to me \$\endgroup\$
    – AZTECCO
    Commented Oct 15, 2022 at 22:27
  • \$\begingroup\$ Not sure is acceptable but at least it should be reusable Try it online! \$\endgroup\$
    – AZTECCO
    Commented Oct 16, 2022 at 11:57
4
\$\begingroup\$

Factor, 33 bytes

[ '[ _ _ bi on t get swap off ] ]

Try it online!

Expects the false-making predicate first and the true-making predicate second.

  • [ ... ] A quotation (anonymous function)...
  • '[ ... ] ...that creates a quotation (anonymous function).
  • _ _ Slot the predicates into the holes.
  • bi Call both predicates on the inner quotation's input value (integer).
  • on Here's where it gets tricky. In Factor, you can use any value as a variable (key) to store something. So what I am doing here is using the result of the true-making predicate to store the value t. It's a little strange to use a canonical boolean value to store a possibly different boolean value, but this is code golf. It's not supposed to make sense, it's just supposed to be short.
  • t get Get the value that is stored in t. This is the result that will be returned from the quotation. This must be done after storing the result of the true-making predicate but before storing the result of the false-making predicate in order to get the 'inclusive' behavior we are looking for.
  • swap Bring the result of the false-making predicate to the top of the stack.
  • off Store f in the result of the false-making predicate.
\$\endgroup\$
4
\$\begingroup\$

R, 54 bytes

{x=F;function(f,g)function(y){x<<-(z=x|f(y))&!g(y);z}}

Try it online!

(or 52 bytes using a global variable to save the current state)


R, 37 bytes (non-competing)

{x=F;function(f,g){x<<-(z=x|f)&!g;z}}

Try it online!

Doesn't fit the written spec of the challenge (the function %..% returns truthy/falsy, rather than a function), but it seems to very well mimic the described behaviour of Ruby's ...

Usage example (to mimic the Ruby example in the challenge):

for(i in 1:20){
    if((i==2)%..%(i==8))print(i)
}
\$\endgroup\$
1
  • \$\begingroup\$ @Jordan - please could you have a look at the 37-byte answer above, which doesn't return a function but seems to me to very well mimic the Ruby .. flip-floperator, and let me know if this is acceptable? Edit: re-reading the spec, I see this isn't acceptable... \$\endgroup\$ Commented Oct 15, 2022 at 8:40
3
\$\begingroup\$

Japt, 29 13 bytes

Ï{T|(T^=YgXgT

Try it

Defines a function which accepts an array of predicates as its input, and returns the flip-flop function. Theoretically should work on strings, numbers, or arrays as the input for the predicate, but I've only tested with numbers.

Ï{T|(T^=YgXgT
              # Initialize T = 0
Ï             # Define a function with argument X (an array of predicates):
 {            #  Return a function with argument Y:
  T           #   Current value of T
   |          #   Bitwise OR
    (T^=      #   T XOR-equals the following:
          XgT #    Get the function in X at index T
        Yg    #    Apply it to Y

A 16 byte alternative doesn't use a global variable, so could be used to define multiple flip flops.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I think a global variable is fine for code golf, and defining a function is fine. \$\endgroup\$
    – Jordan
    Commented Oct 14, 2022 at 19:12
  • \$\begingroup\$ @Jordan I kept the global variable, but I found a shorter answer which is more in line with being a make_flip_flop function \$\endgroup\$ Commented Oct 14, 2022 at 19:23
3
\$\begingroup\$

Python, 76 bytes

-1 byte thanks to py3_and_c_programmer

Takes as input an element i, two lambda functions a and b while using a global variable t to toggle between the true & false cycles.

def f(i,a,b):
 global t
 if~t&a(i):t=1
 if t&b(i):t=0;return 1
 return t
t=0

Attempt This Online!

\$\endgroup\$
2
  • \$\begingroup\$ In Python, you don't really need the ; after t=0 \$\endgroup\$ Commented Oct 15, 2022 at 4:09
  • \$\begingroup\$ @py3_and_c_programmer Well it was an erroneous copy-paste but thanks for pointing out. \$\endgroup\$
    – solid.py
    Commented Oct 15, 2022 at 7:42
3
\$\begingroup\$

Husk, 12 10 bytes

%2ṁ§≠²o⁰←ḣ

Try it online!

%2ṁ§≠²o⁰←ḣ      # 2-argument function, 
                # which yields a partially-applied function
                # requiring 1 further argument:
         ḣ      # 1..further argument   
  ṁ             # map over this and return sum
   §≠           # absolute differences between
     ²          # function arg2 applied to each element, and
      o⁰        # function arg1 applied to 
        ←       # each element plus 1;
%2              # modulo 2.

Example usage f₁₂₃ḣ20

f               # filter
    ḣ20         # 1..20
                # keeping only truthy results of 
 ₁              # function returned by function on line 1
                # called with arguments:    
  ₂₃            # functions on line 2 and line 3
\$\endgroup\$
3
\$\begingroup\$

Rust, 40 bytes

|f|{let mut t=0;move|x|t|{t^=f[t](x);t}}

Try it online!

An expression compatible with fn([fn(T)->usize; 2])->impl Fn(T)->usize for any T. (Yes I know impl Trait can't be used as a return type for fn pointers)

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Right, I updated the code but forgot to change the count & link. \$\endgroup\$
    – corvus_192
    Commented Oct 15, 2022 at 17:13
3
\$\begingroup\$

C++ (clang), 64 bytes

[t=0](auto p){return[=](auto x)mutable{return t|(t^=p[t](x));};}

Port of @Arnauld's JavaScript answer.

Instead of t being a default parameter, it's captured and initialized to 0. The function returns a mutable lambda which captures this t by value along with the predicates container.

This other lambda (the closure) does the heavy lifting, it's declared mutable because it's member t will alternate between the values 0 and 1.

We could save a byte by making the predicates take an int x but it would no longer be generic.

Try it online!

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Capture default.. I love that! \$\endgroup\$
    – AZTECCO
    Commented Oct 15, 2022 at 20:59
  • \$\begingroup\$ Hm, this feels like you cheated a bit, since you need to explicitly specify the template parameter type when using this lambda for it to work correctly. \$\endgroup\$
    – G. Sliepen
    Commented Oct 17, 2022 at 8:21
  • 1
    \$\begingroup\$ @G.Sliepen, it's only used to construct the array, but it doesn't need to be constructed in-place \$\endgroup\$
    – c--
    Commented Oct 17, 2022 at 13:51
3
\$\begingroup\$

C# (.NET Core) 120 117 107 bytes

Here is a C# version based of the Dart and Go examples.

Func<Func<int,bool>,Func<int,bool>,Func<int,bool>>f=(l,r)=>{var s=1<0;return v=>l(v)?s=!s:r(v)?!(s=!s):s;};
  • Shaved off 3 bytes by replacing false with 1<0 and a non needed space. Hat tip to jdt

  • Shaved off 10 bytes by not doing boolean wizardry

Ungolfed main version:

var flipflop = new Func<Func<int,bool>, Func<int, bool>, Func<int,bool>> ( (condition1,condition2) => {
    var flipflop = false;
    return new Func<int,bool>(value => {
        if (condition1(value))
        { 
            flipflop = !flipflop;
        } else if (condition2(value)) {
            flipflop = !flipflop;
            return true;
        }
        return flipflop;
    });
});

How you use it:

var flop = f(v => v == 2, v => v == 8);
for(var x = 0; x< 11; x++) 
{
      if (flop(x)) {
        Console.WriteLine(x);
      }
}

Try it online!

C# (.NET Core), 91 bytes

Using a delegate as proposed by jdt

delegate bool d(int i);Func<d,d,d>f=(l,r)=>{var s=1<0;return v=>l(v)?s=!s:r(v)?!(s=!s):s;};

Try it online!

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

Go, 131 bytes, ints only

func m(l,r func(int)bool)func(int)bool{f:=1<0
return func(t int)bool{if!f&&l(t){f=!f;return f}
if f&&r(t){f=!f;return!f}
return f}}

Attempt This Online!

Go, 132 bytes, generic

func m[T any](l,r func(T)bool)func(T)bool{f:=1<0
return func(t T)bool{if!f&&l(t){f=!f;return f}
if f&&r(t){f=!f;return!f}
return f}}

Attempt This Online!

This solution is fully generic for any type T.

Ungolfed

func makeFlipFlop[T any](l,r func(T)bool) func(T)bool {
	flipped := false
	return func(t T)bool {
		if !flipped && l(t) {flipped = true; return true}
		if flipped && r(t) {flipped = false; return true}
		return flipped
	}
}

Attempt This Online!

\$\endgroup\$
2
\$\begingroup\$

Dart, 42 bytes

f(f,s,[b=1<0])=>(i)=>b?b|(b=!s(i)):b=f(i);

You use it as:

void main() {
  var flipflop = f((i)=>i % 3 == 0, (i) => i % 7 == 0);
  for (var i = 1; i < 15; i++) {
    if (flipflop(i)) print(i);
  }
}

Which prints 3,4,5,6,7,9,10,11,12,13,14.

It even allows you to pass in an extra Boolean to make it the active state.

In a less horribly mangled and more typed version, it would be:

bool Function(T) flipflop<T>(bool Function(T) from, bool Function(T) until) {
  bool b = false;
  return (T value) {
    if (b) {
      b = !until(value);
      return true;
    }
    b = from(value);
    return b;
  }
}
\$\endgroup\$
2
\$\begingroup\$

Nim, 100 bytes

import sugar
var s,t=off
proc f(x,y:int->bool):proc=(z:int)=>(s=s or z.x;t=s;s=s and not z.y;s or t)

Attempt This Online!

Works with int-typed inputs, uses a couple of globals to store the current and previous states.

Unfortunately, Nim doesn't let us omit type annotations, unless we are supplying the lambda directly as an argument to a higher-order function (as in test cases in the footer), so this ends up rather verbose. Importing syntax sugar macros -> and => allows getting rid of some repetitive annotations and thus, pays off by a few bytes.

As a bonus, Nim also allows defining operators, so that we can mimick Ruby's behavior precisely:

Attempt This Online!

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

Pyth, 11 bytes

L+Z=?Z!PbOb

Try it online!

Pyth doesn't have any way to take functions as arguments, nor any way to return a function. So here we do the next best thing, which is to define a function which will implement the required behavior on the two functions O and P. That is to say that when we call y it will flip-flop on whatever O and P are defined as. The try it online link above links to a full working example which is the same as the first example in the question, I'll explain below.

DOdRqd2;                           define O(d): (d==2)
        DPdRqd8;                   define P(d): (d==8)
                L+Z=?Z!PbOb        implement y as the flip-floperator
                           VQyN    loop N over range(0,input()) and print the output of y(N)

And the actual flip-floperator

L              define y(b)
 +Z            sum of previous output and
    ?Z         ternary on previous output
      !Pb          not P(b) if Z currently True
         Ob        O(b) if Z currently False
   =           assign result of ternary to Z
\$\endgroup\$
1
\$\begingroup\$

C++ (clang), 123 101 bytes

struct F{int r=0;template<class A,class B>int operator()(A a,B b,int t){return r|(r^=r?b(t):a(t));}};

Try it online!

  • actually we can go to 92 Bytes if we just implemented a class function h for example but it's no more exactly a closure.

Assumes predicates take int type, generalize also predicates will cost a few Bytes.
Due to implicit type conconversion can work with strings.

Struct F is a closure with operator () defined to behave flipFlop.

Saved 22 Bytes by templatizing operator () instead of the entire class.

Approach stolen from @Arnauld answer where r keeps the state of flipFlop.

\$\endgroup\$
2
  • \$\begingroup\$ 85 bytes but pretty boring. \$\endgroup\$
    – jdt
    Commented Oct 15, 2022 at 13:57
  • \$\begingroup\$ @jdt yes the heavy use of signatures is a bit boring, I also tried a typedef without savings. Anyway now there's c-- great answer so if I touch this will be for deleting \$\endgroup\$
    – AZTECCO
    Commented Oct 15, 2022 at 21:09
1
\$\begingroup\$

PHP 67 bytes

function f($i,$a,$b){static$k=0;$r=$k;return$r|$k^=($k?$b:$a)($i);}

$k must be copied to a temp variable because the ^= is executed before the |,
although both operators are LTR.

Just define your two functions and give them to f as parameters within the loop.
The functions may be anonymous or named, or even predefined.

e.g.

# example 1
$a=function($i){return$i==2;}    $b=function($i){return$i==8;}
for($i=0;$i<=10;$i++) f($i,$a,$b) && print "$i ";

or

# example 2
function a($i){return$i%5==0;}    function b($i){return$i%5==2;}
for($i=0;$i<=10;$i++) f($i,'a','b') && print "$i ";
# important: function names must be quoted to avoid "undefined constant" error (in PHP 8)

or

# other example
for($i=0;$i<=10;$i++) f($i,'intval',function($i){return$i<5;) && print "$i ";
# prints 1 2 3 4 5 6 7 8 9 10
# ('$i<5' is irrelevant because testing 'intval' immediately resumes the printing)

Try it online

\$\endgroup\$

Your Answer

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

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