30
\$\begingroup\$

Introduction and Credit

Today without a fancy prelude: Please implement takewhile.

A variation of this (on a non-trivial data structure) was an assignment at my university functional programming course. This assignment is now closed and has been discussed in class and I have my professor's permission to post it here (I asked explicitly).

Specification

Input

The input will be a list (or your language's equivalent concept) of positive integers.

Output

The output should be a list (or your language's equivalent concept) of positive integers.

What to do?

Your task is to implement takewhile (language built-ins are allowed) with the predicate that the number under consideration is even (to focus on takewhile).

So you iterate over the list from start to end and while the condition (is even) holds, you copy to the output-list and as soon as you hit an element that doesn't make the condition true, you abort the operation and output (a step-by-step example is below). This higher-order functionality is also called takeWhile (takewhile).

Potential corner cases

The order of the output list compared to the input list may not be changed, e.g. [14,42,2] may not become [42,14].

The empty list is a valid in- and output.

Who wins?

This is code-golf so the shortest answer in bytes wins!

Standard rules apply of course.

Test Vectors

[14, 42, 2324, 97090, 4080622, 171480372] -> [14, 42, 2324, 97090, 4080622, 171480372]
[42, 14, 42, 2324] -> [42, 14, 42, 2324]
[7,14,42] -> []
[] -> []
[171480372, 13, 14, 42] -> [171480372]
[42, 14, 42, 43, 41, 4080622, 171480372] -> [42, 14, 42]

Step-by-Step Example

Example Input: [42, 14, 42, 43, 41, 4080622, 171480372]

Consider first element: 42
42 is even (21*2)
Put 42 into output list, output list is now [42]

Consider second element: 14
14 is even (7*2)
Put 14 into output list, output list is now [42,14]

Consider third element: 42
42 is even (21*2)
Put 42 into output list, output list is now [42,14,42]

Consider fourth element: 43
43 is not even (2*21+1)
Drop 43 and return the current output list

return [42,14,42]
\$\endgroup\$
  • 2
    \$\begingroup\$ Is it OK if I return an iterator, rather than a list? \$\endgroup\$ – DJMcMayhem Jul 5 '16 at 19:45
  • 2
    \$\begingroup\$ @DrGreenEggsandIronMan I'm guessing your function has to be able to take its output as its input, guaranteeing they are in the same format. \$\endgroup\$ – mbomb007 Jul 5 '16 at 19:47
  • \$\begingroup\$ @DrGreenEggsandIronMan, I don't think that returning a sublist should be exploited here in the output format. (It's still up to you if you exploit this in your code though). Mbomb's criterion looks most appropriate and compatible with the current challenge so it will be "your output should be a valid input at the very least". \$\endgroup\$ – SEJPM Jul 5 '16 at 20:00

69 Answers 69

0
\$\begingroup\$

tinylisp repl, 61 bytes

(load library)(d E(q((L)(i(i L(even?(h L))L)(c(h L)(E(t L)))(

Defines a function E (short for "take while Even"). Try it online!

Ungolfed

(load library)
(def takewhile-even
 (lambda (ls)
  (if
   (if ls (even? (head ls)) ls)
   (cons (head ls) (takewhile-even (tail ls)))
   nil))))

Recurse through the list, using cons to build the result list. If the list is empty or if even? returns false, return empty list.

Note #1: Your functional programming professor would not like this function. It's not tail-recursive, so it will hit the recursion limit for long lists. Tail-recursive version is 73 bytes:

(load library)(d E(q((L A)(i(i L(even?(h L))L)(E(t L)(c(h L)A))(reverse A

or ungolfed:

(load library)
(def takewhile-even
 (lambda (ls accum)
  (if
   (if ls (even? (head ls)) ls)
   (takewhile-even
    (tail ls)
    (cons (head ls) accum))
   (reverse accum))))

Note #2: The specification of "take while even" actually costs bytes in tinylisp: even? isn't built-in, so we have to load the library (which is expensive) or reimplement the function (which is worse). Generic takewhile with the predicate as a second argument is only 46 bytes:

(d T(q((L P)(i(i L(P(h L))L)(c(h L)(T(t L)P))(

or ungolfed:

(load library)
(def takewhile
 (lambda (ls predicate)
  (if
   (if ls (predicate (head ls)) ls)
   (takewhile (tail ls) predicate)
   nil)))

(I think I may have my next standard library function here...)

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

Java 8, 79 71 bytes

l->{int i=0;for(int n:l){if(n%2>0)return l.subList(0,i);i++;}return l;}

Explanation:

Try it here.

l->{             // Method with ArrayList<Integer> as parameter and List as return-type
  int i=0;       //  Index-integer
  for(int n:l){  //  Loop over the input-List
    if(n%2>0)    //   If the current item is odd:
      return l.subList(0,i);
                 //    Return a sub-List from 0 through index `i` (exclusive)
    i++;         //   At the end of every iteration: increase index `i` by 1
  }              //  End of loop
  return l;      //  If the input-List was empty or contained no odd values, return itself
}                // End of method
\$\endgroup\$
0
\$\begingroup\$

Common Lisp, 44 bytes

 (loop as x in(read)while(evenp x)collect x)

Try it online!

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

Perl 5, 18 + 1 (for a) = 19 bytes

Uses -aE instead of -ae.

$_%2?die:say for@F
\$\endgroup\$
0
\$\begingroup\$

Stax, 9 bytes

{O{|e*cf}

This is a block (equivalent to a function) that takes a list and returns a list on the top of the stack. The link below attaches some footers to output the list.

Run and debug online!

Explanation

{O{|e*cf}
{       }    Define a block
 O           Put 1 under top of stack, used as an accumulator
  {    f     Filter array with accumulator
   |e        True if array element is even, false if odd
     *c      `And` with accumulator
\$\endgroup\$
  • \$\begingroup\$ Does packing not save any bytes? \$\endgroup\$ – caird coinheringaahing Mar 11 '18 at 11:18
  • \$\begingroup\$ Packed content cannot be directly copied to a program as a block that can be called. \$\endgroup\$ – Weijun Zhou Mar 11 '18 at 11:41
0
\$\begingroup\$

Add++, 14 bytes

L*,bU1€+2↑%1€_

Try it online!

How it works

L*,		; Declare 'lambda 1' that returns the stack
		; Example argument:		[[12 14 16 17 18 20]]
	bU	; Unpack;		STACK = [12 14 16 17 18 20]
	1€+	; Increment each;	STACK = [13 15 17 18 19 21]
	2↑%	; Takewhile odd;	STACK = [13 15 17]
	1€_	; Decrement each;	STACK = [12 14 16]
\$\endgroup\$
  • 2
    \$\begingroup\$ Why the downvote? Is there anything wrong with this answer? \$\endgroup\$ – caird coinheringaahing Mar 11 '18 at 17:51
  • 1
    \$\begingroup\$ I don't see anything wrong with it, so I've upvoted to neutralize the unexplained downvote. \$\endgroup\$ – Kevin Cruijssen Mar 12 '18 at 15:59
0
\$\begingroup\$

Javascript (ES2015) , 42 Bytes

I wasn't sure if the expected implementation was of the actual higher order function or the special case of getting a list of all even numbers, so i did both. Byte count is for longest of the two (higher order)

Even numbers (39 bytes)

l=>(o=[],l.every(v=>~v%2&&o.push(v)),o)

Higher order function:

f=>l=>(o=[],l.every(v=>f(v)&&o.push(v)),o)

higher order function called using curry style syntax

f(predicate)(list) => list
\$\endgroup\$
0
\$\begingroup\$

Husk, 3 bytes

↑¦2

Try it online!

After my adventures with using drop-while to set a default input value with Husk's type inference system, I jumped at the opportunity to use take-while for something normal.

↑      The largest prefix of
       the input
 ¦     in which each element is divisible by
  2    two.
\$\endgroup\$
0
\$\begingroup\$

Java (JDK), 58 bytes

a->a.stream().mapToInt(i->i).takeWhile(i->i%2<1).toArray()

Try it online!

Takes a List<Integer> and outputs an int[].

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