59
\$\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\$
24
  • 2
    \$\begingroup\$ Can we use bit lists or other truthy/falsy list representations that are more natural in our language of choice? \$\endgroup\$ May 7, 2017 at 20:32
  • 2
    \$\begingroup\$ Well yeah, if you talk about "truthy" and "falsy" in the challenge instead of "booleans", "true" and "false". ;) \$\endgroup\$ May 7, 2017 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, 2017 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, 2017 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, 2017 at 21:19

75 Answers 75

2
\$\begingroup\$

Batch, 85 73 bytes

:a
@(if %1.==. exit)&set/ar=(1-f)*%1
@echo %r%&set/af^|=%1&shift&goto a

Takes input as command line arguments. For eample: 1.bat 0 1 0 1 0 0 1

Previous version

@set f=1
:a
@(if %1.==. exit)&set/ar=f*%1
@echo %r%&(if %1==1 set f=)&shift&goto a
\$\endgroup\$
2
\$\begingroup\$

Brain-Flak, 230 bytes

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

I will explain soon but my mom cooked me some fried potatoes

([]){{}({}[()]<>)<>([])}{}<>([]){{}({}<>)<>([])}{}<> Subtracts one from every item

({<({}<>)<>>()}<(())>){({}[()]<<>({}<>)>)}{} Loops down stack until current item is zero and adds one

(([])<{{} (({})())({<{}>{}((<()>))}<{}{}>) ({}<>)<>([])}<>>){({}[()]<({}<>)<>>)}{}<> On every item of stack if it is 0 do nothing and if it is -1 add one

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

{}{} Remove the two zeros at top of stack

([]){{}({}<>)<>([])}{}<> Flip stack back

Try it online!

Special thanks

Special thanks to Wheat Wizard and Riley for helping me a ton with code!

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

\$\endgroup\$
10
  • \$\begingroup\$ Can you explain? \$\endgroup\$
    – Adám
    May 7, 2017 at 23:23
  • \$\begingroup\$ Oh, oops, misinterpreted the question. \$\endgroup\$
    – AAM111
    May 7, 2017 at 23:27
  • \$\begingroup\$ Undeleted and fixed the answer \$\endgroup\$
    – AAM111
    May 8, 2017 at 0:03
  • \$\begingroup\$ You can save one byte by making 0 for 0for. \$\endgroup\$
    – Adalynn
    May 8, 2017 at 11:03
  • \$\begingroup\$ It works for 1if and 1else, right? Thanks! \$\endgroup\$
    – AAM111
    May 8, 2017 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)
([])
{
 {}({}<>)<>([])
}<>{}
\$\endgroup\$
0
2
\$\begingroup\$

Perl 5, 12 bytes

10 bytes code + 2 for -pl.

$_&&=!$-++

Try it online!

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

Jelly, 3 bytes

ŒQa

Try it online!

ŒQ was added to the language about two months after the previous Jelly solution.

ŒQ     Nub sieve: for each element, is it the first occurrence of that value?
  a    Take the logical AND of that and the original list.

user62131's solution can also be 3 bytes with a newer builtin:

Jelly, 3 bytes

Ä=a

Try it online!

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

tinylisp, 63 bytes

(d F(q((L B)(i L(c(i B(h L)0)(F(t L)(i(h L)0 B)))(
(q((L)(F L 1

The solution is the anonymous function in the second line; the first line is a helper function. Try it online!

Ungolfed/explanation

(load library)                 ; Library contains ungolfed aliases for builtins

(def F                         ; Define F
  (lambda (L B)                ; as a function that takes a list L and an int B (where B
                               ; is a flag indicating if we're in the beginning section):
    (if L                      ;  If L is nonempty:
      (cons                    ;   Prepend
        (if B (head L) 0)      ;   head of L if B is truthy, else 0
        (F                     ;   to a recursive call
          (tail L)             ;   with tail of L as the new list
          (if (head L) 0 B)))  ;   and 0 as the new flag if head of L is truthy, else B
      nil)))                   ;  Else, return empty list

(lambda (L)                    ; Anonymous function that takes a list
  (F L B))                     ; and passes it to F with a second argument of 1
\$\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.

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

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

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

Scala, 44 bytes

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

PowerShell, 29 bytes

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

Try it online!

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

\$\endgroup\$
2
  • 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\$ May 10, 2017 at 17:03
  • \$\begingroup\$ @ØrjanJohansen Thanks, that's 25 bytes golfed! \$\endgroup\$
    – YSC
    May 11, 2017 at 15:40
1
\$\begingroup\$

PHP, 34 bytes

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

Try it online!

\$\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
\$\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
\$\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)
\$\endgroup\$
3
  • 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\$ Apr 6, 2020 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, 2020 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\$ Apr 7, 2020 at 8:27
1
\$\begingroup\$

Ruby -nl, 22 bytes

Input is STDIN.

a|=p
p !a&&a|=eval($_)

Try it online!

Explanation

                  # For each line of STDIN:
a|=p              # Set a to falsy if it wasn't defined before
                  #  (needed or else the next line crashes)
p !a&&a|=eval($_) # Output false if a is truthy, otherwise OR it with the value in STDIN
                  #  and output that instead
\$\endgroup\$
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

\$\endgroup\$
3
  • \$\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, 2020 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, 2020 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\$ Apr 12, 2020 at 10:57
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 
\$\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)
\$\endgroup\$
1
\$\begingroup\$

Fig, \$6\log_{256}(96)\approx\$ 4.939 bytes

=1*eSk

Try it online!

cumsum builtin when

\$\endgroup\$
2
  • \$\begingroup\$ cumsums == Y@S \$\endgroup\$
    – Seggan
    Oct 12, 2022 at 21:04
  • \$\begingroup\$ @Seggan that's no shorter than eSk \$\endgroup\$
    – naffetS
    Oct 12, 2022 at 23:27
0
\$\begingroup\$

PHP, 61 Bytes

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

Try it online!

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

Japt, 7 bytes

®?!T°:Z

Try it online!

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

\$\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])
\$\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.

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

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

\$\endgroup\$
1
  • \$\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, 2017 at 9:40

Your Answer

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

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