52
\$\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

66 Answers 66

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\$

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\$
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 Apr 6 at 13:44
  • 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 Apr 7 at 8:25
  • 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 Apr 7 at 8:27
1
\$\begingroup\$

[Python 2], 83 68 bytes

I try classic approach.

def t(l,b=1>0):
 r=[]
 for x in l:r+=[x and b];b=(1-x)*b>0
 return r

I use and boolean operator between each value of list and a value that is true until first truely value in list and false after.

es.

list val. --> F F T F T F F
b         --> T T T F F F F
and op.   --> F F T F F F F

Tanks @AdHocGarfHunter

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Welcome to the site. Three improvements I see right away are 1) You can put r=[] in the function arguments just like b=True 2) False is shorter as 1<0 and True as 1>0 3) Your whole if then bit is just not x and b which can be rewritten as (1-x)*b>0. \$\endgroup\$ – Wheat Wizard Apr 11 at 17:16
  • \$\begingroup\$ @AdHocGarfHunter Tanks. There is a problem to side effect of function parameter, if you call more time t function, r accumulate values and b assume False value. \$\endgroup\$ – n1k9 Apr 12 at 9:16
  • 1
    \$\begingroup\$ @n1k9 you're right, I think the consensus here is that a function must be reusable. So r=[] must goes in the body. b is immutable, so it can stay in the arguments. \$\endgroup\$ – Surculose Sputum Apr 12 at 10:57
1
\$\begingroup\$

unsure, 222 bytes

hm um err wait oops um but oops yeah umm err heh well wait oops then but heh wait oops no um um yeah err heh um but oops oops um heh well wait oops then um but oops yeah um err heh well wait then um but oops okay well wait

Unsure is a stack based esolang I recently created. This answer takes input as a string of 0x00 and 0x01 bytes.

First, here's the code broken into more readable sections:

hm um err wait oops

um but oops yeah umm err heh well wait oops then

but heh wait oops no um um yeah err heh

um but oops oops um heh well wait oops then

um but oops yeah um err heh well wait then

um but oops okay well wait

The first section is a loop, which first reads input (hm), and adds one (um err). The wait instruction usually ends a while loop, but because there is nothing to start the loop it defaults to the beginning of the program. Because it's adding 1 to each input, and EOF is -1, the loop will end once it reaches EOF with an additional 0 on the stack, which is discarded by oops.

The next line is a loop through the entire stack. For the first iteration, the stack length is unneeded, so it pushed 1 with um. The but starts a loop, and the oops discards the stack length. It then negates the top of the stack (yeah) and adds two (umm err, essentially the inverse of the input). It finally pushes this to the other stack (heh) and pushes the length of the current stack (well). Once the loop ends, the extra 0 is discarded and then switches the active stack.

The next line consists of two parts: but heh wait oops no (a simple loop which pops items to the other stack until one is 0), then um um yeah err heh which pushes 0 to the other stack.

It then pads the other stack to the right length with 1s (um but oops oops um heh well wait oops) and switches to the other stack (then). This is necessary because the output would be backwards otherwise. The other stack does about the same thing, but inverts each item by negating it and adding one (yeah um err).

Finally, the um but oops okay well wait loop just uses okay to output each item in the stack.

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

K (oK), 13 bytes

Solution:

{@[x;1_&x;~]}

Try it online!

Explanation:

{@[x;1_&x;~]} / the solution
{           } / lambda taking implicit argument x
 @[x;    ; ]  / apply func to target at indices @[target;indices;func] 
          ~   / not, the function being applied
       &x     / indices where x is true
     1_       / drop the first occurrence 
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Python 3, 52 46 44 38 bytes

Input is a list of bools, requires Python 3.8 (for the walrus operator :=).

lambda x,b=0:[a>b and(b:=a)for a in x]

To be called as (lambda x,b=0:[a>b and(b:=a)for a in x])(bools_list)

Previous attempts:

Input is a list of 1s and 0s

lambda x,b=0:[(b:=1)if a>b else 0for a in x]

def f(x):a=[0]*len(x);a[x.index(1)]=1;return a

The above doesn't work with an all-falsey list, list.index throws ValueError if the value isn't present. Edit: and neither do most (all?) other Python 3 entries, for the same reason.

Input x is an iterable of bools, returns iterable of bools.

map(lambda a,b=[0]:not(b[-1]or b.append(a)or 1-a),x)
| improve this answer | |
\$\endgroup\$
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\$

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\$

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.