42
\$\begingroup\$

Background

Inspired by Octave's (and, by extension, MATL's) very convenient interpretation of truthy/falsy matrices, Jelly got the Ȧ (Octave-style all) atom.

Ȧ takes an array as input and returns 1 if the array is non-empty and does not contain the number 0 (integer, float, or complex) anywhere in the tree structure; otherwise, it returns 0.

For example, the array [[]] is truthy because it is non-empty and contains no zeroes, but [[0]] is falsy because it contains a 0 at the innermost level.

Task

In a programming language of your choice, write a full program or a function that takes a possibly empty, possibly jagged array of integers as input and prints or returns a truthy or falsy value that indicates if Ȧ would return 1 or 0, respectively.

Your submission must abide to the following rules.

  • The truthy and falsy values must be consistent for all inputs, i.e, all arrays for which Ȧ returns 1 must map to the same truthy value, and all arrays for which Ȧ returns 0 must map to the same falsy value.

  • Since full programs can only take string representations of arrays as input, this is allowed. However, you must use the canocical representation of your language, as returned by repr or similar.

    In particular you cannot assume that the first element of the array will be preceded by a space.

  • If (and only if) your language cannot represent jagged arrays natively, you may take a string representation of the input, using the canonical syntax of any pre-existing programming language.

  • If your language has several ways of representing jagged arrays (e.g., lists and tuples), you only have to support one of them.

  • If your language has a built-in that is itself a valid submission to this challenge, you may not use it in your answer. All other built-ins are allowed.

  • You are encouraged to post answers using both array and string manipulation, even if one is significantly shorter than the other.

  • All standard rules apply.

May the shortest code in bytes win!

Truthy test cases

[1]
[10]
[[]]
[[[[1]]]]
[[], [1], [1, 2]]
[[1], [1, [2]], [1, [2, [3]]]]
[[8], [8, [9]], [8, [9, [10]]]]

Falsy test cases

[]
[0]
[0, -1]
[-1, 0]
[[[[0]]]]
[[0], [1, 2], [3, 4, 5]]
[[8], [8, [9]], [8, [9, [1, 0]]]]
[-1, 0, 0, 0]
\$\endgroup\$
19
  • \$\begingroup\$ Based on the test cases, do you mean "contain the number 0" to mean anywhere in the tree structure? That's not what I have guessed it meant. \$\endgroup\$
    – xnor
    Commented Mar 18, 2017 at 17:35
  • \$\begingroup\$ Yes, anywhere. I'll try to clarify that. \$\endgroup\$
    – Dennis
    Commented Mar 18, 2017 at 17:36
  • \$\begingroup\$ What exactly do you mean "you cannot assume that the string representation will have a particular format"? \$\endgroup\$
    – Dada
    Commented Mar 18, 2017 at 17:40
  • 4
    \$\begingroup\$ These are not jagged arrays - jagged arrays would have all numbers at the same depth, because only sizes vary, not element types. \$\endgroup\$ Commented Mar 18, 2017 at 18:41
  • 4
    \$\begingroup\$ @Qwertiy Right, "most" languages where "everything" is an Object... my favorite is Haskell, where it isn't. Nor in C, at least not in a way that allows you to mix arrays and ints safely. Both of those languages are perfectly capable of jagged arrays, but still cannot use them for this problem. \$\endgroup\$ Commented Mar 18, 2017 at 23:41

48 Answers 48

39
\$\begingroup\$

Jelly, 3 bytes

ṭFẠ

F flattens the input list.

tacks on the original input list as an element, which is falsy if and only if it is empty.

then checks if any element in the flattened list, or the original list itself, is falsy.


(Original answer)

FẠ^Ṇ

Thanks to Dennis for encouraging finding a solution matching his.

FẠ gives 0 if the input contains a falsy value at any depth, else 1. This is what Ȧ does, except for empty lists.

gives 1 if the input is a falsy value, else 0. The only falsy list is the empty list.

XOR-ing the two gives the answer.


F;WẠ

This is much in the same spirit as Dennis's F;LẠ, but instead of using L to put a zero in the list when the list is empty, it uses W to put the empty list into itself (producing [[]]), making it contain a falsy element.

\$\endgroup\$
1
  • 35
    \$\begingroup\$ Outgolfed in my own challenge and my own language... Well done! \$\endgroup\$
    – Dennis
    Commented Mar 19, 2017 at 23:08
16
\$\begingroup\$

Retina, 10 bytes

A`\b0
^...

Try it online!

First we remove the input if it contains a zero. The we try to match at least three characters from the beginning of the string (to ensure that the input hasn't been eliminated in the previous stage, or was only [] to begin with).

\$\endgroup\$
12
\$\begingroup\$

Ruby, 25 24 23 18 16 bytes

p$_!~/\D0|^..$/

Requires the -n flag on the command line (+1 byte, -e -> -ne).

Try it online!

This is a full program that takes input in Ruby's canonical array format on STDIN and outputs true or false on STDOUT.

 $_              # line of input that was read automatically (-n)
   !~/        /  # does not match the regex...
      \D0        #   a non-digit followed by a 0
         |       #   or...
          ^..$   #   a 2-length string (which must be [], the empty array)
p                # output the result

23 byte function version:

->a{"#{a}"!~/\D0|^..$/}

This is a proc that takes one argument, the array to be tested.

Thanks to Martin Ender for a byte and to Ventero for two bytes!

\$\endgroup\$
2
  • \$\begingroup\$ You could save two more bytes by using p$_!~/\D0|^..$/ (or p ! ~/\D0|^..$/, yay significant whitespace) together with the -n flag. \$\endgroup\$
    – Ventero
    Commented Mar 19, 2017 at 14:16
  • \$\begingroup\$ Very late, but you can get 13 bytes using apparently undocumented behaviour of !. \$\endgroup\$
    – Dingus
    Commented Jun 1, 2020 at 11:20
8
\$\begingroup\$

Jelly, 4 bytes

FẠ_Ṇ

Try it online!

Ȧ yields 0 if the input is empty or contains a 0, otherwise it is 1.

FẠ yields 0 if the flattened input contains a 0, leaving only the edge case of an empty array (since the input is guaranteed to be an array).

is a non-vectorising logical not monad, and hence returns 0 for any non-empty list and 1 for the empty list. As such this can simply be subtraced from the result of FẠ using _.

\$\endgroup\$
9
  • \$\begingroup\$ One down, at least one more to go. \$\endgroup\$
    – Dennis
    Commented Mar 19, 2017 at 0:07
  • \$\begingroup\$ @Dennis It isn't FẠạṆ, right? \$\endgroup\$ Commented Mar 19, 2017 at 8:01
  • \$\begingroup\$ @EriktheOutgolfer No, it is not. The answer I have in mind deals different with the edge case of an empty array and would produce a different result for non-arrays. \$\endgroup\$
    – Dennis
    Commented Mar 19, 2017 at 14:48
  • \$\begingroup\$ @Dennis Like returning A for True, B for false, C for empty and D for non-array? That would be non-competing. What I did is use absolute difference instead of difference because there are no negative booleans. \$\endgroup\$ Commented Mar 19, 2017 at 14:56
  • \$\begingroup\$ @EriktheOutgolfer B must equal C to comply with the challenge spec, but D can be anything as the input is guaranteed to be an array. \$\endgroup\$
    – Dennis
    Commented Mar 19, 2017 at 14:59
8
\$\begingroup\$

APL (Dyalog), 21 12 7 bytes

Golfed 5 bytes thanks to Adám by using forks

⍬∘≡⍱0∊∊

Try it online!

This is my first try at Dyalog. Golfing tips are welcome!

Explanation

⍬∘≡                   Fork; Is the argument a null set
   ⍱                  Nor
    0∊∊               0 belongs to the enlisted form of the argument
                      For example, (1 (2 (3 (0)))) would become
                      1 2 3 0 using the ∊ monad
                      Then we check if zero belongs to this vector
\$\endgroup\$
2
  • \$\begingroup\$ +1 Note that you are combining the results of two tests. This is perfect for a fork. ⍬∘≡ is the left test (empty-set bound-to identical-to), and 0∊∊ is the right test (itself a fork; zero member-of enlisted-form). Put it together: ⍬∘≡⍱0∊∊. Try it online! \$\endgroup\$
    – Adám
    Commented Mar 18, 2017 at 21:42
  • \$\begingroup\$ Also, you may want to use the name "APL (Dyalog)" so people can find what it is you are using. \$\endgroup\$
    – Adám
    Commented Mar 18, 2017 at 21:43
8
\$\begingroup\$

05AB1E, 9 8 bytes

-1 bytes thanks to Emigna

)Q¹˜0å~_

Explanation:

)Q        Is the length of the input 0?
  ~    _  ... NOR ... (just for you, Dennis) 
   ¹˜     Input deep flattened
     0å   Contains 0

Try it online!

\$\endgroup\$
6
  • \$\begingroup\$ Seems to fail for [[]]. \$\endgroup\$
    – Dennis
    Commented Mar 18, 2017 at 17:45
  • 1
    \$\begingroup\$ Is 0 really truthy in 05AB1E? \$\endgroup\$
    – Dennis
    Commented Mar 18, 2017 at 17:46
  • \$\begingroup\$ all arrays for which Ȧ returns 1 must map to the same truthy value, and all arrays for which Ȧ returns 0 must map to the same falsy value (emphasis mine) \$\endgroup\$
    – Dennis
    Commented Mar 18, 2017 at 17:53
  • 1
    \$\begingroup\$ @Dennis Alright, chucked in a logical negation byte there. \$\endgroup\$
    – Okx
    Commented Mar 18, 2017 at 17:55
  • 1
    \$\begingroup\$ Aw, just for me. :P \$\endgroup\$
    – Dennis
    Commented Mar 18, 2017 at 17:56
7
\$\begingroup\$

Mathematica, 17 bytes

#!={}&&#~FreeQ~0&

FreeQ does the check against 0 for us, but of course it would return True for input {}, so we need to check that case separately.

\$\endgroup\$
7
\$\begingroup\$

Operation Flashpoint scripting language, 199 188 bytes

A={f={private["_i","_r"];_r=1;_i=0;while{_i<count _this}do{o=_this select _i;if(o in [o])then{if(o==0)then{_r=0}}else{_r=o call f};_i=_i+1};_r};if(count _this==0)then{0}else{_this call f}}

Call with:

[3,6,4,[4,6],[3,6,[],[2,4,[0],3]]] call A

or with:

hint format["%1", [3,6,4,[4,6],[3,6,[],[2,4,[0],3]]] call A]

Explanation:

In the game's scripting language, any string containing code can be called. The curly braces {} denote the beginning and the end of a string. (Quotation marks work too, but that gets messy when they are nested.) So, A={...} assigns a string to variable A, and the variable can then be called like a function with: <argument> call A. Basically any string can be treated as a block of code.

Then, inside the "function" A, we define another function f. private declares the two variables _i and _r local to function f. A local variable's name has to start with an underscore.

while {} do {} is a loop, where the first string (denoted by {}) contains the code for the loop condition and the second one for the loop body.

_this is the argument that was passed with the call function. _this can be of any type, but here we assume it is an array.

In the loop, o=_this select _i accesses the _i:th element of the array and assigns it to variable o. if (o in [o]) is a trick to determine if the o is another array or not. If o is a number (or anything other than an array), o in [o] will evaluate to true, because the in function finds a value matching o from the array [o]. If o is an array, the expression yields false, because the in refuses to compare arrays.

If o is not an array, we check if it equals zero, and if it does, we'll set the variable _r, which we'll use as the return value, to zero. Otherwise, if o is an array, we assign to _r the return value of the recursive call to f with the new array o as the argument.

After the loop, at the end of function f, we evaluate the expression _r, which yields the value of _r, and as this is the last expression to be evaluated, this is what the call to function f returns.

Now that we have defined f (f need not be inside A, but this way we could have declared it a local variable/function (no difference really) of A if we didn't want to save some bytes), let's get back A. if (count _this == 0) checks if A's input array is empty, and if it is, A returns 0. Otherwise the function f is called and its return value will be A's return value.

One might notice that it seems that a semicolon would be missing from a few of places, but this is not the case, because a semicolon is only needed after a statement if another statement follows it inside the same block of code (i.e. string).

\$\endgroup\$
5
  • \$\begingroup\$ Wait, what?! Operation Flashpoint? \$\endgroup\$ Commented Mar 20, 2017 at 13:23
  • \$\begingroup\$ wat how? what??? confuzed \$\endgroup\$
    – user63187
    Commented Mar 20, 2017 at 15:30
  • \$\begingroup\$ @DownChristopher Added an explanation. \$\endgroup\$
    – Steadybox
    Commented Mar 20, 2017 at 16:24
  • 1
    \$\begingroup\$ @AnderBiguri Yep, why not? The game's scripting language fits the definition of programming language given in the meta post linked in the question. \$\endgroup\$
    – Steadybox
    Commented Mar 20, 2017 at 16:25
  • 1
    \$\begingroup\$ @Steadybox I am confused about the existence of the thing, not its validity!! \$\endgroup\$ Commented Mar 20, 2017 at 16:35
5
\$\begingroup\$

Perl 5, 15 bytes

Saved 2 bytes by using the same technique as Doorknob's Ruby answer.

14 bytes of code + -p flag

$_=!/\b0|^..$/

Try it online!

/.../ ensures that the array isn't empty (it will match on any array but [].
/\b0/ will only match if there is a 0 in the array. (the \b ensures that the 0 isn't a part of another number but a whole number).

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

Haskell, 48 bytes

f x=or[elem c"[,"|c:'0':_<-scanr(:)[]x]<(x<"[]")

Try it online!

Thanks to Lynn for the test cases and the x<"[]" trick.

The outer inequality requires (x<"[]") to be True (nonempty list) and or[elem c"[,"|c:'0':_<-scanr(:)[]x] to be False (no zeroes).

Characters of 0 are detected as following a , or [, as opposed to a number like 20. The expression scanr(:)[]x generates all suffices of l, and c:'0':_<- captures those whose second character is '0'. Then, elem c"[," checks whether the first character is , or [.

I assume here that Haskell-style lists don't have spaces, but if so ',' can just be replaced by ' '.

Here's a more direct 48-byte method, though it produces 0's and 1's which aren't Truthy/Falsey in Haskell.

f"[]"=0
f(c:'0':_)|elem c"[,"=0
f(_:t)=f t
f _=1
\$\endgroup\$
5
\$\begingroup\$

Jelly, 4 bytes

F;LẠ

Try it online!

How it works

F;LẠ  Main link. Argument: A (array)

F     Flatten A.
  L   Yield A's length.
 ;    Concatenate.
   Ạ  All; Tell if all elements of the resulting 1D array are truthy.

Note that the Ạ atom behaves like Python's all and thus is rather different from the banned Ȧ.

\$\endgroup\$
1
  • 9
    \$\begingroup\$ Heads-up: This isn't the only 4-byte solution Jelly, apart from the obvious L;FẠ. Who can find another one? \$\endgroup\$
    – Dennis
    Commented Mar 18, 2017 at 19:54
4
\$\begingroup\$

Julia, 45 bytes

a(x)=all(a,x);a(x::Int)=x!=0;g(x)=x!=[]&&a(x)

This creates a function g that indicates whether Ȧ would be 1 or 0 by calling a recursive function a. To make a suitable a, we use multiple dispatch:

# A method for scalar values
a(x::Int) = x != 0

# A recursive fallback for arrays
a(x) = all(a, x)

The function all takes a function argument, so we're calling a on each element of the input. Then we simply define the function for the submission as

g(x) = x != [] && a(x)

Basically we just need a but with a check to correctly handle [].

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ can you define the function a(x) or g(x) as !x instead? \$\endgroup\$
    – Cyoce
    Commented Mar 20, 2017 at 18:24
4
\$\begingroup\$

Grime, 16 14 11 bytes

Thanks to Zgarb for saving 5 bytes.

e`s\0v#|!..

Try it online!

The e tells Grime to try and match the entire input and print 0 or 1 depending on whether that's possible.

The |! is effectively a "neither" operator, because x|!y is shorthand for (x|y)!. So we make sure that the input neither contains a zero preceded by a symbol nor is a string of only two characters ([]).

A note about the second half: P# matches a rectangle that contains at least one match of P. However, in our case P consists of both s and \0 so that would normally require parentheses: (s\0)# (because the precedence of # is too high). But Grime has a really neat feature where you can modify the precedence of operators with ^ and v. So by using v# we lower #'s precedence so that it's lower than that of any other operator (including concatenation), which lets us save a byte on the parentheses.

\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES6), 34 bytes

a=>a.length&&+!~`,${a}`.search`,0`

Test cases

let f =

a=>a.length&&+!~`,${a}`.search`,0`

console.log('Truthy:')
console.log(f([1]))
console.log(f([10]))
console.log(f([[]]))
console.log(f([[[[1]]]]))
console.log(f([[], [1], [1, 2]]))
console.log(f([[1], [1, [2]], [1, [2, [3]]]]))
console.log(f([[8], [8, [9]], [8, [9, [10]]]]))

console.log('Falsy:')
console.log(f([]))
console.log(f([0]))
console.log(f([0, -1]))
console.log(f([-1, 0]))
console.log(f([[[[0]]]]))
console.log(f([[0], [1, 2], [3, 4, 5]]))
console.log(f([[8], [8, [9]], [8, [9, [1, 0]]]]))

\$\endgroup\$
2
  • \$\begingroup\$ You can probably use !!a[0] instead of a.length. (You don't have to worry about a[0] being zero as the result must be false in this case anyway.) \$\endgroup\$
    – Neil
    Commented Mar 18, 2017 at 23:54
  • \$\begingroup\$ Never mind, I saw Qwerty already got there. \$\endgroup\$
    – Neil
    Commented Mar 18, 2017 at 23:57
3
\$\begingroup\$

Pip, 12 bytes

#Va&`\b0`NIa

Takes the array as a command-line argument in Pip's repr form, like [1;[2;3]]. Returns 1 for truthy, 0 for falsey. Try it online or verify all test cases.

Explanation

              a is 1st cmdline arg (implicit)
 Va            Eval a (converting from a string to a list)
#              Take the length (0 if empty, nonzero if nonempty)
   &          Logical AND
    `\b0`      Regex pattern: word boundary followed by 0 (avoids things like 10)
         NIa   Not in a (0 if `\b0` matches in a, 1 if it doesn't)
              Autoprint

Bonus answer, 12 bytes

Here's a function that takes a list instead:

#_>0=0N_Js^s

#_            Len(arg)
  >0          is greater than 0
    =         which also equals the following (comparison operators chain like Python's):
     0N       Count of 0's in
       _Js^s  arg, joined on space and then split on space (a hacky way to flatten)

TIO

\$\endgroup\$
3
\$\begingroup\$

Röda, 59 44 bytes

f a{[1]if{g(a)[[]!=a]}}g a{[a!=0];try a|g _}

Try it online!

f takes the input from its stream as a list that can contain other lists and integers. It returns 1 if a is truthy and nothing otherwise. The helper function g checks if a contains zeros.

Explanation:

f a{[1]if{g(a)[[]!=a]}}
f a{                  } /* Function declaration */
          g(a)          /* Call g -> pushes some booleans to the stream */
              [[]!=a]   /* Push value []!=a to the stream */
       if{           }  /* If all booleans in the stream are true: */
    [1]                 /*   Push 1 to the stream */
                        /* Otherwise return nothing */

g a{[a!=0];try a|g _}   /* Helper function */
g a{                }   /* Function declaration */
    [a!=0];             /* Push value a!=0 to the output stream */
           try          /* Ignore errors in the following if a is not a list */
               a        /* Push values in a to the stream */
                |g _    /* Pull values from the stream and */
                        /*   call g for each of them */
                        /*   (pushes boolean values to the output stream) */

A solution that makes use of regexes could very likely be shorter.

This answer could have been shorter if it were allowed to return multiple values. This has been discussed in one of my answers before, and it was concluded that it is allowed in the default rules to return different truthy and falsy values for different inputs, but for some reason OP forbid it here and there. :(

\$\endgroup\$
3
\$\begingroup\$

Wonder, 15 bytes

@&#0! iO0flat#0

Usage:

(@&#0! iO0flat#0)[1;2;3;[8;9;0]]

Flatten input, get all occurrences of 0, logical NOT, logical AND with input.

\$\endgroup\$
3
\$\begingroup\$

Haskell, 62 bytes

import Data.List
(%)=isInfixOf
f x=not(",0"%x||"[0"%x)&&x<"[]"

Try it online!

This is a function String -> Bool. Haskell’s lists are heterogenous, so there’s no built-in way to represent lists like [0, [0]].

\$\endgroup\$
2
  • \$\begingroup\$ Based on the re-worded rules, the inputs should not have spaces because Haskell arrays don't by default. At least, I think that's the interpretation even though Haskell doesn't allow jagged arrays. But it looks like your code would work the same with , for ` `. \$\endgroup\$
    – xnor
    Commented Mar 18, 2017 at 18:40
  • 2
    \$\begingroup\$ As I'm quibbling up in the question comments, Haskell does have jagged arrays (and lists) - it's just that it's not really enough for what this question requires. \$\endgroup\$ Commented Mar 18, 2017 at 23:44
3
\$\begingroup\$

Python 2, 45 39 38 bytes

lambda a:(a>[])^(' 0'in`a`or'[0'in`a`)

Try it online!

-6 thanks to @BenFrankel


previous version, without converting list to string repr, 68 bytes:

lambda a:(len(a)and g(a))*1
g=lambda b:all(map(g,b))if b>[]else b!=0
\$\endgroup\$
1
  • \$\begingroup\$ This gives a false positive on []. The following saves 6 bytes and succeeds on []: lambda a:bool(a)^(' 0'in`a`or'[0'in`a`) \$\endgroup\$ Commented Mar 18, 2017 at 23:30
2
\$\begingroup\$

MATLAB, 49 bytes

As MATLAB (as well as Octave) does not allow these kind of nested arrays, we interpret it as a string.

First we replace all non-digit characters with a space. Then we use str2num to convert it to an (1D) array, on which we can apply all (which is allowed, as it does not completely solve this task by itself.)

s=input('');s(s<45|s>57)=32;disp(all(str2num(s)))
\$\endgroup\$
2
\$\begingroup\$

egrep, 7+3=10 bytes

\<0|^.]

+3 bytes for the required -v flag to invert the result.

Grep doesn't have any concept of arrays, so this uses a string representation as given in the question. Takes input on one line from stdin, returns via the exit code (ignore stdout).

(Now using a version which doesn't account for 01 and similar, since word-of-god is that it's OK)

Original bash/grep entry:

grep -Ev '\<0+\>|^.]'

Finds 0s anywhere (using the word boundary checks \< and \> to discount things like 10 or a1), or a whole string matching [], then inverts the match.

Breakdown:

grep
     -E \    # extended regular expression syntax
     -v \    # invert match
     \<0+\>  # a number of 0s with alphanumeric boundaries on both sides
     |^.\]   # or ']' as the second character (implies '[]')
\$\endgroup\$
2
  • \$\begingroup\$ Not cheating, just good golfing. :) Btw, grep is capable for primality testing, so it is a programming language as far as PPCG is concerned. \<0\|^.] plus -v would count as an 11 byte solution. \$\endgroup\$
    – Dennis
    Commented Mar 18, 2017 at 21:44
  • 1
    \$\begingroup\$ @Dennis cool, thanks! (I switched to egrep rather than grep to save an additional byte; language name doesn't count towards byte-count!) \$\endgroup\$
    – Dave
    Commented Mar 18, 2017 at 22:09
2
\$\begingroup\$

√ å ı ¥ ® Ï Ø ¿ , 12 4 bytes

i0Bu

Explanation

i            › Take input as a list and automatically flatten it. If empty, push 0.
 0           › Push 0 to the stack
  B          › Pop 0 and push the number of times it appears
   u         › convert top value to its boolean 

If result needs to be outputted ...

i0Buo        › same as above; o outputs the top value on the stack

Previous solution

I had posted this before realising that stack based languages could leave the value on the stack as a form of output

i0B¿0oP?!¿o?

Explanation

i            › Take input as a list and automatically flatten it. If empty, push 0.
 0           › Push 0 to the stack
  B          › Pop 0 and push the number of times it appears
   ¿         › If the top value is true ...
    0        › Push 0
     o       › Output the top value on the stack
      P      › Pop the top value from the stack
       ?     › End if statement
        !    › Boolean opposite of top value
         ¿   › If the top value is true ...
          o  › Output the top value
           ? › End if statement
\$\endgroup\$
2
\$\begingroup\$

Haskell, 45

As Lynn and xnor remarked, Haskell does not come with a heterogeneously-nested list type. But it's easy to add them as a custom data type and let the function operate on that type, and this is much preferrable to operating on (urgh!) strings.

data L=L Int|T[L]
f(L n)=n/=0
f(T l)=all f l

To actually be able to write out such lists as literals with [1, [2]] syntax, you also need some typeclass fu. Full test case:

{-# LANGUAGE OverloadedLists, TypeFamilies #-}
import GHC.Exts (IsList(..))

instance Num L where
  fromInteger = L . fromInteger
  negate (L n) = L $ negate n
instance IsList L where
  type Item L = L
  fromList = T
main = mapM_ (print . f) (
                    [ [1]
                    , [[[[0]]]]
                    , [[8], [8, [9]], [8, [9, [1, 0]]]]
                    ] :: [L])

Try it online!

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

Vim, 23 bytes

:g/0\|^..$/d
:s/.\+/1/<CR>

Try it online!

Outputs an empty string for false, or 1 for true. This could be shorter if I can output an empty string or [] for false (both of which are falsy values in vim).

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

Javascript ES6, 24 23 chars

Works with array, returns true or false:

a=>!!a[0]>/\b0/.test(a)

Test:

f=a=>!!a[0]>/\b0/.test(a)

console.log([
  [1],
  [10],
  [[]],
  [[[[1]]]],
  [[], [1], [1, 2]],
  [[1], [1, [2]], [1, [2, [3]]]],
  [[8], [8, [9]], [8, [9, [10]]]],
].every(x => f(x)===true))

console.log([
  [],
  [0],
  [0, -1],
  [-1, 0],
  [[[[0]]]],
  [[0], [1, 2], [3, 4, 5]],
  [[8], [8, [9]], [8, [9, [1, 0]]]],
].every(x => f(x)===false))

\$\endgroup\$
8
  • \$\begingroup\$ Since the return value can be truthy/falsy, you can drop the !! (though then you must change & to &&). Saves one byte. \$\endgroup\$ Commented Mar 21, 2017 at 3:19
  • \$\begingroup\$ @BrianMcCutchon, no as there is a binary &. In case of && without !! consistent output will be broken: undefined for [],0 for [0] and [0,1,2] and false for others. \$\endgroup\$
    – Qwertiy
    Commented Mar 21, 2017 at 4:30
  • \$\begingroup\$ I don't see how breaking consistent output is bad in this challenge. My point with switching to && is that you would need to if you take my first suggestion, since 2 & 1 == 0. \$\endgroup\$ Commented Mar 21, 2017 at 4:41
  • \$\begingroup\$ @BrianMcCutchon, the first point of the question: "The truthy and falsy values must be consistent for all inputs, i.e, all arrays for which Ȧ returns 1 must map to the same truthy value, and all arrays for which Ȧ returns 0 must map to the same falsy value." \$\endgroup\$
    – Qwertiy
    Commented Mar 21, 2017 at 4:44
  • \$\begingroup\$ Ah, I skimmed that too quickly. Never mind. \$\endgroup\$ Commented Mar 21, 2017 at 4:45
1
\$\begingroup\$

Stacked, 20 bytes

:size\flat,0 eq none

Try it online!

Alternatively, using a string:

:tostr'\d+'match'0'has¬\size¬>

Try it online!

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

Lithp, 74 bytes

(def f #L::((foldl(flatten L)(?(>(length L)0)1 0)#N,A::((?(== N 0)0 A)))))

Try it online!

Well, this turned out longer than I'd hoped. The [] case tripped me up and added a few bytes. It simply flattens the list and does a fold left over it, and if it finds a 0 it sets the accumulator to 0.

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

Ruby, 24 22 bytes

->a{a[0]&&a*?!!~/\b0/}

Try it online!

Yes I know there's a better solution in Ruby but I wanted to find one taking the array in input instead of a string.

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

VIM: 16 keystrokes 28 keystrokes 26 keystrokes

Had to add a bunch of keystrokes to take care of multiple zeros and the empty array [].

i[] 0<enter><esc>A 0<esc>h#dd0%r602x<C-x>$hd0<C-a>

Expects the array to be in the first and only line of the file and the cursor to be on the first character. Leaves 0 for false and a 1 for true.

Explanation

  1. i[] 0<Enter><esc> Writes some stuff preceding the array
  2. A 0<esc> Writes some stuff preceding the array
  3. #dd search for the word "0", going backwards in the document and delete the line it's containing.
    • If 0 is in the array, this will stop on the second line.
      1. This leaves [] 0 on the first line, which is an empty array.
    • Else, this will stop on the first line, leaving the line (array) 0

At this point, all that's left to do is to identify the empty array and output 0 if it's present, otherwise ignore it.

The possible way for a 0 to be at the third position is if it is the empty array. Thus, it's just a problem for identifying if the third character is a 0.

  1. 3|a01<esc> Writes 01 after the third character
  2. 0df0 Deletes up to the first zero.
  3. lD saves the next character, then deletes the rest of the line.

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ The program doesn't work for [-1, 0, 0, 0] \$\endgroup\$
    – user41805
    Commented Mar 23, 2017 at 9:41
  • \$\begingroup\$ I was able to golf it smaller and detect multiple zeros, but then discovered it also currently fails for []. \$\endgroup\$
    – Dominic A.
    Commented Mar 25, 2017 at 3:18
1
\$\begingroup\$

tinylisp, 70 64 bytes

(load library
(d _(q((X)(i(c()X)(all(map _ X))X
(q((L)(i L(_ L)0

The last line is an unnamed lambda function that takes a list and returns 1 for "truthy-under-Ȧ" and 0 for falsey. Try it online!

Ungolfed

(load library)

(def _Ȧ
 (lambda (val)
  (if (equal? (type val) List)
   (all (map _Ȧ val))
   val)))

(def Ȧ
 (lambda (ls)
  (if ls
   (_Ȧ ls)
   0)))

The recursive helper function does most of the work. If its argument is a list, we map to its elements and return 1 if they are all truthy, 0 if any are falsey. (Conveniently, all returns 1 when given the empty list.) Otherwise, the argument must be an integer; we return it as-is (0 is falsey and all other integers are truthy in tinylisp).

The main function Ȧ checks if the list is nonempty. If so, it calls ; if not, it returns 0.

The golfed version takes advantage of some undefined behavior: rather than using (e(type X)List) to test whether X is an integer or a list, it does (c()X), which attempts to cons (prepend) the empty list onto X. If X is a list, this results in a nonempty list, which is truthy. If X is an integer, tinylisp outputs an error message and returns an empty list, which is falsey. Since stderr is ignored, this approach is valid.

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