Title is an homage to this classic challenge
In Pip, the Scalar data type encompasses strings and numbers. A Scalar value is truthy in most cases. It is falsey only if:
- It is the empty string
""; or - It is some representation of the number zero.
A Scalar is considered to be a representation of zero if:
- It consists of one or more
0s; or - It consists of one or more
0s plus a single.anywhere among them.
The decimal point can be in the middle, at the beginning, or at the end.
Challenge
Given a string containing printable ASCII characters, determine whether it is a truthy Scalar or a falsey Scalar according to Pip.
The default allowable output formats for decision-problem apply: you may either output a truthy/falsey value in your language, with swapping allowed, or choose two consistent values, one representing truthy and the other representing falsey.
This is code-golf; the goal is to minimize the size of your source code, measured in bytes.
Examples
Falsey:
""
"0"
"000"
".0"
".00"
"0."
"00."
"0.00"
"0000000000000.00000000000000"
Truthy:
"abc"
"x"
"0001"
"0x00"
"0e0"
" 0"
"0 "
"+0"
"-0"
"."
"0.0.0"
"0.00000000000000000000000001"
Reference implementation
This Python 3 code is adapted from the actual Pip interpreter:
import re
zeroRgx = re.compile(r"^(0+(\.0*)?|0*\.0+)$")
def truthy(value):
return value != "" and not zeroRgx.match(value)
24 Answers 24
-
\$\begingroup\$ I feel there should be a better way using
float... \$\endgroup\$Rhaixer– Rhaixer2022年12月30日 12:31:12 +00:00Commented Dec 30, 2022 at 12:31 -
8\$\begingroup\$ @UndoneStudios I don't know.
floatdoesn't feel like a good match. First, it has three different outcomes (zero, non-zero and exception). Second, it accepts stuff like0e1,0_0,+0and even0.<lots of zeros>1for zero while rejecting the empty string. So making it work seems a lot of trouble. \$\endgroup\$Albert.Lang– Albert.Lang2022年12月30日 14:46:14 +00:00Commented Dec 30, 2022 at 14:46 -
\$\begingroup\$ how does this work?? lol i dont get it \$\endgroup\$DialFrost– DialFrost2023年01月01日 09:10:43 +00:00Commented Jan 1, 2023 at 9:10
-
1\$\begingroup\$ @DialFrost It uses Python operator chaining to check that after removing all leading and trailing zeros there is nothing or a single dot left while explicitly ruling out just a single dot (and no zeros). \$\endgroup\$Albert.Lang– Albert.Lang2023年01月01日 13:46:21 +00:00Commented Jan 1, 2023 at 13:46
-
1\$\begingroup\$ @DialFrost It looks confusing because he's abusing comparison chaining. For non golf purposes it would look more like
((s.strip("0") in ".") and ("." != s)). Fun stuff, nice answer. \$\endgroup\$CursorCoercer– CursorCoercer2023年01月05日 22:39:55 +00:00Commented Jan 5, 2023 at 22:39
05AB1E, 7 bytes
„+-2‡{Ā
Try it online or verify all test cases.
Explanation:
‡ # Transliterate in the (implicit) input-string
„+- # all "+" and "-"
2 # to "2" and "6" respectively
{ # Sort all characters in this string (based on codepoint)
Ā # 'Python-style' truthify this sorted string
# (which is output implicitly as result)
The new 05AB1E is built in Elixir.
With just Ā, the 0. and 00. test cases are incorrectly truthy instead of falsey and the +0, -0, and 0e0 test cases are incorrectly falsey instead of truthy. The sort { is to fix 0., 00., and 0e0 and the transliterate „+-2‡ to fix +0 and -0.
05AB1E (legacy), 8 bytes
...+- 1‡{Ā
Try it online or verify all test cases.
Explanation:
‡ # Transliterate in the (implicit) input-string
„+- # all "+", "-", and " "
1 # to "2", "5", and "6" respectively
{Ā # Same as above
# (after which the result is output implicitly)
The legacy version of 05AB1E is built in Python 3.
With just Ā, the 0, 0 , +0, -0, and 0e0 test cases are incorrectly falsey instead of truthy. The transliterate ...+- 1‡ is to fix 0, 0 , +0, and -0, and sort { is to fix 0e0 (thanks to @JonathanAllan for noticing a bug with this 0e0 test case).
2sable, (削除) 11 (削除ここまで) (削除) 10 (削除ここまで) 9 bytes
'.Q«Ô0Þså
Outputs an inverted boolean.
Try it online or verify all test cases.
Explanation:
'.Q '# Check if the (implicit) input is equal to "."
« # Append this 1 or 0 to the (implicit) input
Ô # Connected uniquify (uniquifies groups of adjacent equal characters)
0 # Push integer 0
Þ # Floatify and then stringify it: "0.0"
så # Check if the connected uniquify string is a substring of this
# (so one of "", "0", "0.", ".0", "0.0", or "."†)
# (which is output implicitly as result)
2sable is built in Python 3 as well, and is the oldest of the three versions and predecessor of the legacy 05AB1E version.
It lacks a lot of the builtins, including the Ā we use in the other two programs, so I had to find an alternative. I ended up using the connected uniquify builtin Ô and check whether the result is one of "", "0", "0.", .0", "0.0". I do this by checking whether it's a substring of "0.0".
† After which only the "." test case would incorrectly give a truthy instead of falsey result, which I've fixed by adding a leading '.Q«.
Trivial Pip answers, 1 byte
Thanks to decision-problem defaults, the identity function/program is a solution in Pip, since it turns falsey inputs into falsey outputs and truthy inputs into truthy outputs. Therefore, either of these full programs will work when given input as a command-line argument:
a
g
This program will work when given input on stdin:
q
And this works as a function solution:
_
While we're at it, logically negating the input gives some two- and three-byte solutions:
!a
!q
\!_
I'm making this post as a community wiki to head off these obvious answers (and other trivial solutions such as @g or {a} that are basically the same thing but longer). You are encouraged to post your own non-trivial Pip solutions.
-
\$\begingroup\$ I really don’t get why people always upvote the CW for boring answers to oblivion... \$\endgroup\$noodle person– noodle person2023年10月26日 12:12:34 +00:00Commented Oct 26, 2023 at 12:12
Charcoal, 9 bytes
∧No.−θ0−.θ
Try it online! Link is to verbose version of code. Outputs . for truthy, nothing for falsy. Note: Due to bugs in Charcoal's input, you need to input an empty string using a blank line. Explanation: Port of @Albert.Lang's Python answer.
No Count of
θ Input string
− 0 With `0`s removed
. In literal string `.`
∧ Logical And
. Literal string `.`
− θ With input string removed
-
\$\begingroup\$ The newer version of Charcoal on ATO doesn't have the JSON input bug so you can use that to input an empty string: Attempt This Online! \$\endgroup\$Neil– Neil2022年12月30日 09:51:20 +00:00Commented Dec 30, 2022 at 9:51
Retina 0.8.2, (削除) 16 (削除ここまで) 15 bytes
1`0\.|\.0
^0*$
Try it online! Link includes test cases. Explanation:
1`0\.|\.0
Delete at most one . adjacent to a 0.
^0*$
Match any number of zeros.
-
\$\begingroup\$ My previous version
^(?!\.$)0*\.?0*$is still a 16-byte Regex answer, which ties with @Bubbler's answer, although it requires negative lookahead, which means that it's not quite as universal. \$\endgroup\$Neil– Neil2023年01月06日 08:44:24 +00:00Commented Jan 6, 2023 at 8:44
Acc!!, 107 bytes
Count i while 1-_/4 {
_*524+N
53308230694/5^(_/131+2*0^(_%131-48)^2+0^(_%131-46)^2+_^130%131)%5+1
}
Write _
Takes the input NULL-terminated, returns chr(5) for truthy and chr(4) for falsey.
53308230694 encodes this table (minus 1, which is later added), which represents the transitions of a FSM for this language, and the rest of the code just converts the input to the correct format.
| State\Input | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 0 | 5 | 4 | 3 | 1 |
| 1 | 5 | 4 | 2 | 1 |
| 2 | 5 | 4 | 4 | 2 |
| 3 | 4 | 4 | 4 | 2 |
Where 0 is "null byte", 1 is "invalid character", 2 is ".", and 3 is "0". The state 4 is rejected, and 5 is accepted.
Vyxal, (削除) 11 (削除ここまで) (削除) 9 (削除ここまで) 8 bytes
0円o\.¤"c
Uses inverted booleans (1 for false and 0 for true).
-2 thanks to @pacman256
Explanation
0円o\.¤"c # Implicit input
0円o # Remove all 0s from the input
c # Is this new string in the following list:
\.¤" # [".", ""]?
# Implicit output
-
\$\begingroup\$ vyxal.pythonanywhere.com/… 9 bytes before vyncoding \$\endgroup\$pacman256– pacman2562023年10月24日 12:49:35 +00:00Commented Oct 24, 2023 at 12:49
-
\$\begingroup\$ I just noticed that this fails the test case
"."(truthy in Pip, meaning your program should return0). \$\endgroup\$DLosc– DLosc2024年07月17日 19:50:25 +00:00Commented Jul 17, 2024 at 19:50
Factor + math.unicode, 45 bytes
[ dup "0"without "."subseq? swap "."≠ and ]
Returns t for falsey and f for truthy.
With zeros removed, is it a sub-sequence of "."? And is the original input not equal to "."?
Pip, (削除) 16 (削除ここまで) 13 bytes
aRM0N'.&!aQ'.
-3 bytes thanks to @DLosc
Non-trivial pip answer, port of @Albert.Lang's answer
Go, 106 bytes
import."regexp"
func f(s string)bool{return len(s)>0&&!MustCompile(`^(0+(\.0*)?|0*\.0+)$`).MatchString(s)}
Port of the reference regexp.
R, 36 bytes
\(s)trimws(s,,0)%in%c("",".")&s!="."
Port of @Albert.Lang's answer.
Uses the whitespace argument of the trimws function introduced in R 3.6.0.
Python 3, (削除) 73 (削除ここまで) (削除) 72 (削除ここまで) (削除) 67 (削除ここまで) (削除) 66 (削除ここまで) 64 bytes
lambda v:not re.match("^(0+(\.0*)?|0*\.0+)$",v)and""<v
import re
Golfed reference implementation from @DLosc.
-
\$\begingroup\$ you don't need
""<, you can just output truthy/falsey \$\endgroup\$naffetS– naffetS2023年01月01日 14:47:12 +00:00Commented Jan 1, 2023 at 14:47 -
\$\begingroup\$ @Steffan then it'll fail when
v=""as the 1st truthy testcase \$\endgroup\$DialFrost– DialFrost2023年01月01日 21:16:07 +00:00Commented Jan 1, 2023 at 21:16 -
\$\begingroup\$ No it won't, just boolify the result first \$\endgroup\$naffetS– naffetS2023年01月01日 21:16:33 +00:00Commented Jan 1, 2023 at 21:16
-
\$\begingroup\$ Hint: my regex isn't the golfiest possible regex ;) \$\endgroup\$DLosc– DLosc2023年01月02日 05:47:49 +00:00Commented Jan 2, 2023 at 5:47
Google Sheets, (削除) 37 (削除ここまで) 34 bytes
=regexmatch(A1,"^0*\.?0*$")*(A1<>".")
Put the input in cell A1 and the formula in B1. Outputs 1 for falsey and 0 for truthy.
Using Bubbler's regex:
=regexmatch(A1,"^0*(0\.|\.0)?0*$")
Outputs TRUE for falsey and FALSE for truthy.
Uiua, (削除) 33 bytes (削除ここまで) 28 bytes (SBCS)
Edit: Using Bubbler's improved regex.
=0⧻regex"^0*(0\\.|\\.0)?0*$"
Not much to explain here - it just matches the regex with the input string and checks that the number of matches is 0.
Idiomatic Uiua, 39 bytes
(0;|(↥⊃'>⊢(<⊢⇌)∶1|1;)∊0∩/+⍉.∺="0.")>0⧻.
Explanation:
(0;| )>0⧻. # If the length is 0 return 0. Otherwise:
∺="0." # Produce a matrix of matches with '0' and '.'
⍉. # Make a copy and transpose it
∩/+ # In both the original and transposed matrices, add up each row
( |1;)∊0 # If there is a 0 in the per character array
# (signifying a character other than '0' or '.'),
# return 1. Otherwise:
∶1 # Put a 1 on the stack and swap the top two items
⊃ # Apply both of the next functions to the same values
(<⊢⇌) # Reverse the array and check if 1 < the first value
# (This tests that the number of '.' chars is > 1)
'>⊢ # Check if 1 > the first value
# (This tests that the number of '0' chars is < 1)
↥ # Return the maximum of the two checks
# (This will return 0 if the number of '0' chars >= 1 AND the number of '.' <= 1)
Uiua, 18 bytes
<∩≍¬⊚.=@.⊃▽'△しろさんかく.≠@0.
Initially based on chunes' Factor answer, but it evolved a lot from it. Returns 1 if the input is falsy, 0 otherwise.
<∩≍¬⊚.=@.⊃▽'△しろさんかく.≠@0. input: a string S
≠@0. keep S and push its non-zero-digit mask
⊃▽ S with zeros filtered out
=@. is-dot mask of above
∩≍¬⊚. C1:is it the same as boolean negation of its nonzero indices?
(the length can be equal only if the mask is all ones, and the content equal only if
the length is zero or one, i.e. the array is [] or [1].
this tests if the input without zeros is either empty or a sole dot.
now we need to filter out the case where S = ".")
∩≍ ⊃ '△しろさんかく. C2:take the non-zero-digit mask, and test if it is the same
as its shape
(this test passes only if the array is [1])
< test if C1 is true and C2 is false
More explanation on the C1 condition:
The input is a boolean vector. ⊚ (where) on it collects the zero-based indices of ones, e.g. [1, 0, 1, 1, 0, 0, 1] becomes [0, 2, 3, 6]. The "logical negation" ¬ calculates 1-x for each value x in the array, e.g. [0, 2, 3, 6] becomes [1, -1, -2, -5].
For the input to equal its ¬⊚, the following conditions need to be met:
- The lengths are equal. For a boolean vector input,
⊚generates a vector whose length is the count of ones in the input. To meet the length requirement, the input vector must be all ones. - The individual values are equal. Since the input is boolean, the output must be also boolean (either 0 or 1).
¬maps 2 or higher to negative numbers, so the original input cannot contain a 1 at indices 2 or higher. This reduces the candidates to[],[1], and[1,1].
Now we can do an exhaustive check:
input -> ⊚ -> ¬⊚
[] -> [] -> []
[1] -> [0] -> [1]
[1,1] -> [0,1] -> [1,0]
Therefore ≍¬⊚. checks if the given boolean vector is either [] or [1].
-
\$\begingroup\$ Nice work. It took me way too long to figure out "the same as boolean negation of its nonzero indices," though--maybe it would help if you broke that part of the explanation into multiple steps? \$\endgroup\$DLosc– DLosc2023年11月01日 15:58:41 +00:00Commented Nov 1, 2023 at 15:58
Pyth, 10 bytes
-scSQ".0"0
Try it online! or Try the full test suite
Outputs an empty string (falsy in pyth) for falsy and a nonempty string (truthy in pyth) for truthy.
Explanation
# Implicitly assign Q = eval(input())
SQ # sort input
c ".0" # split on ".0" (this occurs a maximum of once in a sorted string)
s # concatenate list of strings back into a string
- 0 # remove all "0"s from string
-
\$\begingroup\$ @DLosc You are correct, I guess I was assuming that the returns needed to be consistent for all truthy/falsy cases. \$\endgroup\$CursorCoercer– CursorCoercer2023年01月10日 14:55:05 +00:00Commented Jan 10, 2023 at 14:55
JavaScript (Node.js), 15 bytes
s=>-s!=0+s+'e0'
- If
sis number, thens==0to make it false.e0avoids anotherein number(0e0). - If
sis.,xoro, then-sisNaN - If
sis0or0, then0+s+0is NaN
Assumes double handle enough logrange
Swift 6, (削除) 58 (削除ここまで) (削除) 54 (削除ここまで) (削除) 53 (削除ここまで) 39 bytes
{!(0ドル+"").contains(/^(?!\.$)0*\.?0*$/)}
Alternatively (same byte count):
{(0ドル+"").contains(/[^0.]|\..*\.|^\.$/)}