48
\$\begingroup\$

Intro

Every year, Dyalog Ltd. holds a student competition. The challenge there is to write good APL code. This is a language agnostic edition of this year's eighth problem.

I have explicit permission to post this challenge here from the original author of the competition. Feel free to verify by following the provided link and contacting the author.

Problem

Given a Boolean* list, "turn off" all the Truthies after the first Truthy.

No Truthies? No problem! Just return the list unmodified.

Examples

[falsy,truthy,falsy,truthy,falsy,falsy,truthy][falsy,truthy,falsy,falsy,falsy,falsy,falsy]

[][]

[falsy,falsy,falsy,falsy][falsy,falsy,falsy,falsy]


* All your truthies must be identical, and all your falsies must be identical. This includes output.

\$\endgroup\$
  • 2
    \$\begingroup\$ Can we use bit lists or other truthy/falsy list representations that are more natural in our language of choice? \$\endgroup\$ – Martin Ender May 7 '17 at 20:32
  • 2
    \$\begingroup\$ Well yeah, if you talk about "truthy" and "falsy" in the challenge instead of "booleans", "true" and "false". ;) \$\endgroup\$ – Martin Ender May 7 '17 at 20:36
  • 1
    \$\begingroup\$ I'm not clear on the booleans. Can we use 0/1 even if our language has True/False? \$\endgroup\$ – xnor May 7 '17 at 20:59
  • 1
    \$\begingroup\$ @xnor Ah, good point. I think it would be fair to allow choosing input, but output must match, don't you think so? \$\endgroup\$ – Adám May 7 '17 at 21:12
  • 1
    \$\begingroup\$ @xnor I hear you, but if Haskell cannot treat numbers as Booleans, or cannot do arithmetic on Booleans, then that is a real limitation in the golfing power of Haskell, and ought to be reflected in the byte count by necessitating conversions or other work-arounds. What do you think of the footnote formulation? \$\endgroup\$ – Adám May 7 '17 at 21:19

57 Answers 57

1
2
2
\$\begingroup\$

Python 3, 69 66 64 60 54 53 bytes

lambda i:[k==i.index(j)and j for k,j in enumerate(i)]

Takes an array of falses and trues. This is a list comprehension of falses except if the current iteration's value is true and it is the first true in the input.

This seems a little long (and it's my first lambda), so if you can find a way to golf it, it would be greatly appreciated!

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Can you explain? \$\endgroup\$ – Adám May 7 '17 at 23:23
  • \$\begingroup\$ Oh, oops, misinterpreted the question. \$\endgroup\$ – OldBunny2800 May 7 '17 at 23:27
  • \$\begingroup\$ Undeleted and fixed the answer \$\endgroup\$ – OldBunny2800 May 8 '17 at 0:03
  • \$\begingroup\$ You can save one byte by making 0 for 0for. \$\endgroup\$ – Zacharý May 8 '17 at 11:03
  • \$\begingroup\$ It works for 1if and 1else, right? Thanks! \$\endgroup\$ – OldBunny2800 May 8 '17 at 11:08
2
\$\begingroup\$

Brain-Flak, 146 144 bytes

([]){{}({}<>)(())<>([])}{}<>((())){{}({}<>)<>}{}<>(()){{}((){[()](<{}>)}{})(<>)<>}<>(())<>([]){{}(<{}<>>)<>([])}{}<>{}{}([]){{}({}<>)<>([])}<>{}

Try it online!

# Reverse the stack and add a 1 between each to help with reversing later
([]){{}({}<>)(())<>([])}{}<>

# Add a 1 in case there aren't any truthy values (and another 1 like before)
((()))

# Reverse the stack back to it's original order using the 1s from earlier to know when to stop
{{}({}<>)<>}{}<>

# Push 1 to start the loop
(())

# Until we find the first 1
{

 # Pop the last value
 {}

 # Logical not
 ((){[()](<{}>)}{})

  # Put a 0 on the other stack
  (<>)<>

# end loop
}

# Put a 1 on the other stack
<>(())<>

# Push the stack height
([])

# While there are values on this stack
{

 # Move them to the other stack as a 0
 {}(<{}<>>)<>([])

# End while
}{}

# Pop an extra 0
{}

# Switch stacks
<>

# Copy everything back (to reverse it back to it's original)
([])
{
 {}({}<>)<>([])
}<>{}
|improve this answer|||||
\$\endgroup\$
2
\$\begingroup\$

Perl 5, 12 bytes

10 bytes code + 2 for -pl.

$_&&=!$-++

Try it online!

|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

Cubix, 14 bytes

W;@.1I?>O;w..W

Try it online

Cubix doesn't have proper lists or booleans, so we take the input as a sequence of space-separated 1s and 0s terminated with a -1.

Unfolded

    W ;
    @ .
1 I ? > O ; w .
. W . . . . . .
    . .
    . .

Explanation

The instruction pointer starts at the top of the left face of the cube, moving to the right.

Initially, we push a 1 onto the stack. We then take one input at a time, with I and branch with ?.

If the input is 0, we see O;, which outputs 0 and pops it from the stack.
If the input is 1, we see ;O;, which pops the 1 from the stack, outputs the top of the stack (which will be 1 the first time around), then pops it from the stack.
If the input is -1, we see @, which ends the program.

|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

Ruby, 32 bytes

->a{i=1;a.map{|x|x&&[i,i=p][0]}}

Uses 1 for truthy and nil for falsy.

Explanation

->a{           # take an array a
    i=1;       # use i to keep track of if we've gotten a truthy value yet
    a.map{|x|  # for each element x in a:

        x&&[     # if x is truthy:
              i,     # remember the old i,
              i=p    # then set i to false
           ][0]      # and replace x with the old i
    }
}
|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

vim, 19 keystrokes

2/1<ENTER>i<ENTER><ESC>:s/1/0/g<ENTER>kJx

2/1<ENTER>i<ENTER><ESC> puts everything after the first 1 to the second line and moves the cursor to that line. :s/1/0/g<ENTER> replaces the 1s with 0s. kJx then merges the lines.

|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

Perl 6, 19 bytes

{@_ «&&»[\^^] @_}

This is an anonymous function that takes its arguments in @_. ^^ is the exclusive-or operator, and [\^^] does a scan using that operator, returning a copy of the input list where the first truthy value is replicated until the second truthy value, whereupon it and all remaining values become Nil (which is falsy). To falsify the replicated copies of the first truthy value, if any, the list is combined with the original using &&, the boolean and operator.

|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

Javascript, 25 bytes

x=>x.map(c=>c&&x&&!(x=0))
  • x holds the original array.
  • Once the first truthy has been found, x is overwritten with a false value.
  • This makes c && x return false for all values except the first truthy.
|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

Scala, 44 bytes

s=>{var b=1>2;s.map{x=>if(b)!b else{b=x;x}}}
|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

PowerShell, 29 bytes

$args|%{$_-and!$b;$b=$b-or$_}

Try it online!

|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

OCaml, 85 60 bytes

let rec f?(b=true)=function h::t->(h&&b)::(f~b:(h<b)t)|_->[]

Ungolfed

let rec f ?(b=true) = function
    | head :: tail -> (head && b) :: (f ~b:(head<b) tail)
    | _            -> []

Explanation

f is defined as a recursive function taking an optional (?) boolean b and an unnamed list (function) and return according to the cases:

  • if the first element of the list is false, returns it unchanged,
  • if the first element if the list is true, sets it to b and flip b to false (id est, only let unchanged the first true since b is true by default and then set to false),
  • if the list is empty (end of recursive call), returns the empty list.

Usage

Try it online (you'll need to copy/paste the function definition) !

# f [];;
- : bool list = []
# f [false];;
- : bool list = [false]
# f [true];;
- : bool list = [true]
# f [false;true;true;false;true;true;false;true;false;false];;
- : bool list =
[false; true; false; false; false; false; false; false; false; false]

History

25 (yes, twenty-five) bytes golfed off by Ørjan Johansen, suggesting to merge the first two cases (see explanation).

|improve this answer|||||
\$\endgroup\$
  • 1
    \$\begingroup\$ You can merge the first two cases: let rec f?(b=true)=function c::t->(c&&b)::(f~b:(c<b)t)|_->[]. \$\endgroup\$ – Ørjan Johansen May 10 '17 at 17:03
  • \$\begingroup\$ @ØrjanJohansen Thanks, that's 25 bytes golfed! \$\endgroup\$ – YSC May 11 '17 at 15:40
1
\$\begingroup\$

PHP, 34 bytes

foreach($_GET as$g)echo$f?0:$f=$g;

Try it online!

|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

F#, 79 76 72 bytes

let rec f o=function|[],_->o|x::y,1->f(o@[0])(y,1)|x::y,_->f(o@[x])(y,x)

Try it online!

Usage

let input = [0;0;0;0;1;1;0;0;1]
printfn "%A" f [] (input, 0)

Explanation

This is a very straightforward implementation.

f is a function with two arguments, first being the result list and the second a tuple of input and a value indicating if a truthy value has been found.

Note: only 1 is considered truthy, every other number is falsy. Which sounds weird now that I think about it. This however, can easily be changed so that any value <> 0 is truthy. But I think it should be ok the way it is, as expected input is only 0 or 1

// int list -> int list * int -> int list
let rec f output = function
| [], _ -> output                      // return result
| x::xs, 1 -> f (output@[0]) (xs,1)    // if truthy was encountered before, append 0 to result, process rest of input
| x::xs, _ -> f (output@[x]) (xs,x)    // if not, append 0 or 1 to result, process rest of input
|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

05AB1E, 5 bytes

ε¾›D½

Try it online!

explanation:

ε for each value in the (implicit) input
¾ push the counter variable
› check if it's bigger than the current value (0 0 - 0, 0 1 - 1, 1 0 - 0, 1 1 - 0)
D duplicate
½ increment the counter variable if it's true (which means that if the current value is 1 and the counter is 0, increment it)
|improve this answer|||||
\$\endgroup\$
  • 1
    \$\begingroup\$ Nice approach. I just had this 5-bytes alternative, which I added as a comment under the existing 05AB1E answer: ηOøPΘ. :) \$\endgroup\$ – Kevin Cruijssen 2 days ago
  • 1
    \$\begingroup\$ @KevinCruijssen Isn't that trivially the same as ηO*Θ for 4 bytes? My 5-byter was RƶRZQ (or ƶWQ by bending the I/O rules a bit), interesting how different our three approaches are. \$\endgroup\$ – Grimmy yesterday
  • 1
    \$\begingroup\$ @Grimmy Ah, I'm an idiot. You're indeed completely right that ηO*Θ works for 4 bytes. And another nice alternative! EDIT: And I like that 3-byter, since only 1 is truthy in 05AB1E. xD I actually had something similar with ƶWQ in mind at first, but it obviously failed since 0 is lower. Hadn't thought about using a different falsey value, which technically is valid in 05AB1E, although indeed kinda bending the I/O rules. xD \$\endgroup\$ – Kevin Cruijssen yesterday
0
\$\begingroup\$

PHP, 61 Bytes

$n=[];foreach($_GET as$v)$n[]=$n&&max($n)?0:$v;print_r($n);

Try it online!

|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

Japt, 7 bytes

®?!T°:Z

Try it online!

|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

77 Bytes, Javascript

var s=0;[0,0,0,1,0,0].forEach(function(c,i,a){if(c||s)s=c=1;console.log(c)});

I/O are zeros and ones.

|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

F#, 88 bytes

let c2 u=
 let n=ref(1<0)
 [for i in u do if !n||not i then yield 1<0 else n:=i;yield i]

Use as follows:

let mutated = c2 [true; true; false; false; true]

or

printfn "%A" (c2 [true; false; true; false; true])
|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

AWK, 31 bytes

BEGIN{ORS=RS=" "}$1{$1=t-->-1}1

Try it online!

Assumes input is space-separated 1 and 0. Most of the code is just splitting the records on for input and output. The variables could be assigned via command-line options, but it only saves a couple bytes and TIO doesn't count them. :(

BTW

BEGIN{ORS=RS=" "}$1&&t++{$1=0}1

also works, but I find it a bit harder to read and has the same byte-count, anyway.

|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

Chip, 10 bytes

,.
`z.
a\A

Try it online!

How?

The elements a\A will copy the lowest bit of input (A) to the lowest bit of output (a) so long as the switch is inactive (\).

When A is powered, due to a truthy input, it activates the delay element (z) via a wire (.). This delay element will wait one cycle -- that is, until the next input byte -- at which point it will send the signal onward. This activates the switch, cutting off the input from the output, and via some more wires (` , .) activates itself for the next cycle.

If you change the normally-closed switch \ for a normally-open switch /, you'd get a circuit that filters out only the first truthy value.

|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

ReRegex, 18 bytes

1(0*)1/1$10/#input

Fairly simple solution, ReRegex takes all pairings of 1(0*)1, which is two 1s with any amount of 0s in between, and just leaves the first 1, replacing the second with a 0. As ReRegex keeps running the regex until no more change happens, which satisfies the challenge.

Try it online!

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ This solution removes ones from the input, but I believe the challenge asks to turn them into zeros. This can be fixed by adding a final 0 to the substitution pattern \$\endgroup\$ – Leo May 8 '17 at 9:40
0
\$\begingroup\$

Retina, 16 bytes

+T`1`0`(?<=1)0*1

Try it online! My first Retina submission ever.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ 0*1 can be replaced with .* \$\endgroup\$ – eush77 May 20 '17 at 22:38
0
\$\begingroup\$

C++, 77 75 bytes

Yay pointers and memset!

void f(bool*a,int b){bool*c=&a[b];while(a<c)if(*a++)break;memset(a,0,c-a);}

Function takes in a pointer to a bool array, and the length of that array as parameters. It loops through the array until it finds the first true, increments one more cell, and memsets the remainder of the memory from that pointer until the end. 0 length arrays work too since the loop is skipped entirely and the memset gets 0 bytes as the length, however passing in null instead of an empty array will break things.

Ungolfed + tests

#include <iostream>
#include <cstdlib>
#include <cassert>

//void f(bool*a,int b){bool*c=&a[b];while(a<c)if(*a++)break;memset(a,0,c-a);}

void f(bool* a, int b)
{
    bool* c = &a[b];
    while (a < c)
        if (*a++)
            break;
    memset(a, 0, c - a);
}

void print(bool* a, int b)
{
    for (int i = 0; i < b; i++)
    {
        std::cout << a[i] << '\t';
    }
    std::cout << std::endl;
}

int main()
{
    size_t s = sizeof(bool);
    assert(s == 1);
    bool* t1 = new bool[5] { false, false, false, false, false };
    bool* t2 = new bool[0];
    bool* t3 = new bool[6] { false, false, true, false, true, true };
    bool* t4 = new bool[10] { true, true, true, true, true, true, true, true, true, true };
    f(t1, 5);
    f(t2, 0);
    f(t3, 6);
    f(t4, 10);
    print(t1, 5);
    print(t2, 0);
    print(t3, 6);
    print(t4, 10);
    delete[] t1;
    delete[] t2;
    delete[] t3;
    delete[] t4;
}
|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

Befunge-98, 19 bytes

&:1`#@_1*:.70g\-70p

Try it online!

Input: stream of numbers, 0 (false), 1 (true), or 2 (EOF).

Output: stream of numbers, 0/1.

Explanation

The program works by reading the next number in a loop, multiplying it by a constant, and printing the result to stdout. The operation described in the problem statement is performed by modifying that constant:

&:1`#@_1*:.70g\-70p
       ^          v
       [ P[7]-= x ]
|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

CJam, 10

{_1#\,,f=}

Try it online!

Explanation:

This is a function that takes an array of 0 and 1 from the stack, and pushes the resulting array on the stack.

_      duplicate the array
1#     find the index of the first 1 (it is -1 if not found)
\      swap with the other copy of the array
,      get the array length, let's call it n
,      make an array [0 1 … n-1]
f=     compare each element with the index we got earlier
|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

Whitespace, 66 bytes

[S S S N
_Push_0][N
S S N
_Create_Label_LOOP][S N
S _Dupe_0][S N
S _Dupe_0][S N
S _Dupe_0][T    N
T   T   _Read_STDIN_as_integer][T   T   T   _Retrieve_integer][T    S S T   _Subtract][N
T   T   S N
_If_negative_Jump_to_Label_FIRST_TRUTHY][S S S N
_Push_0][T  N
S T _Print_as_integer][N
S N
N
_Jump_to_Label_LOOP][N
S S S N
_Create_Label_FIRST_TRUTHY][S S S T N
_Push_1][S N
S _Dupe_1][T    N
S T _Print_as_integer][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).

The input is newline separated, and the output is all joined together. If this is not allowed, it's 80 bytes (both newline separated) or 82 bytes (both joined together) instead.
Uses 1 for truthy and 0 for falsey.

Explanation in pseudo-code:

Integer flag = 0
Start LOOP:
  Integer input = STDIN as integer
  If(flag - input < 0):
     Jump to Label FIRST_TRUTHY
  Print 0 as integer to STDOUT
  Go to next iteration of LOOP

FIRST_TRUTHY:
  flag = 1
  Print 1 as integer to STDOUT
  Go to next iteration of LOOP
|improve this answer|||||
\$\endgroup\$
-1
\$\begingroup\$

PowerShell, 25 bytes

$args|%{$_-and!$f;$f+=$_}

Previous "non legal" version

{$_*!$f;if($_){$f=1}}

Try it online!

The one more version with the same length of 25 bytes

$args|%{!!$f-lt$_;$f+=$_}

Try it online!

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Is this a legal answer? I am honestly not sure. You cannot run this on its own as a function or program. It is a process scriptblock for the foreach-object cmdlet. I would have expected you to use $args \$\endgroup\$ – Matt May 8 '17 at 18:34
  • \$\begingroup\$ @Matt I would say no, it's not legal. \$\endgroup\$ – briantist May 9 '17 at 20:05
  • \$\begingroup\$ @briantist Well that is good then. I don't feel the need to go back to my old answers now. \$\endgroup\$ – Matt May 9 '17 at 20:06
  • 1
    \$\begingroup\$ @Matt here's the relevant clarification for PowerShell specifically. \$\endgroup\$ – briantist May 9 '17 at 20:08
1
2

Your Answer

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

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