Repost and improvement of this challenge from 2011
A vampire number is a positive integer \$v\$ with an even number of digits that can be split into 2 smaller integers \$x, y\$ consisting of the digits of \$v\$ such that \$v = xy\$. For example:
$1260ドル = 21 \times 60$$
so \1260ドル\$ is a vampire number. Note that the digits for \$v\$ can be in any order, and must be repeated for repeated digits, when splitting into \$x\$ and \$y\$. \$x\$ and \$y\$ must have the same number of digits, and only one can have trailing zeros (so \153000ドル\$ is not a vampire number, despite \153000ドル = 300 \times 510\$).
You are to take a positive integer \$v\$ which has an even number of digits and output whether it is a vampire number or not. You can either output:
- Two consistent, distinct values
- A (not necessarily consistent) truthy value and a falsey value
- For example, "a positive integer for true, 0 for false"
You may input and output in any convenient method. This is code-golf, so the shortest code in bytes wins.
The first 15 vampire numbers are \1260,ドル 1395, 1435, 1530, 1827, 2187, 6880, 102510, 104260, 105210, 105264, 105750, 108135, 110758, 115672\$. This is sequence A014575 on OEIS. Be sure to double check that your solution checks for trailing zeros; \153000ドル\$ should return false.
15 Answers 15
Husk, (削除) 18 (削除ここまで) (削除) 17 (削除ここまで) (削除) 14 (削除ここまで) (削除) 13 (削除ここまで) 12 bytes
Edit: -3 bytes, and then another -1 byte, thanks to Leo, and -1 byte thanks to inspiration from pajonk's R answer (3rd edit)
1ドルmΠ†dm1⁄2f→Pd
Outputs nonzero integer if it's a vampire number, zero otherwise.
Commented penultimate version:
1ドル # index of input if present, zero otherwise, in
mΠ # products of each element-pair
†d # combining digits as a number from
m1⁄2 # first & second halves of
P # all permutations of
d # digits of input;
f # and filtering only element-pairs for which
ṁ→ # sum of last digits is nonzero
-
\$\begingroup\$ Nice one! I believe the condition to your filter can be simplified to just
ṁ→(sum of the last element of each half) saving three bytes \$\endgroup\$Leo– Leo2021年02月08日 23:59:52 +00:00Commented Feb 8, 2021 at 23:59 -
\$\begingroup\$ And 1 more byte saved by using deep map
†! tio.run/##ASUA2v9odXNr///igqzCuW3OoOKAoGRm4bmB4oaSbcK9UGT///… \$\endgroup\$Leo– Leo2021年02月09日 00:03:17 +00:00Commented Feb 9, 2021 at 0:03 -
1\$\begingroup\$ @Leo - That's amazing! Thanks! I never really figured-out the difference between
mand†: this is the first time that I've seen them behave differently, so I'm still struggling to understand what's going on... (and why†let's us avoid theohere...) \$\endgroup\$Dominic van Essen– Dominic van Essen2021年02月09日 00:11:37 +00:00Commented Feb 9, 2021 at 0:11 -
1
R, (削除) 156 (削除ここまで) (削除) 146 (削除ここまで) (削除) 143 (削除ここまで) (削除) 135 (削除ここまで) 145 bytes
-10 bytes thanks to Dominic van Essen.
+10 bytes fixing error pointed by DialFrost.
function(n,s=strsplit){for(i in 1:n)if(!n%%i&nchar(j<-n/i)==nchar(i)&all(sort(el(s(paste0(j,i),'')))==sort(el(s(c(n,''),''))))&j%%10)return(T)
F}
In newer R, 130 bytes
\(n,`+`=\(x)sort(el(strsplit(x,"")))){for(i in 1:n)if(!n%%i&nchar(j<-n/i)==nchar(i)&all(+paste0(j,i)==+c(n,''))&j%%10)return(T)
F}
-
2\$\begingroup\$ Really nice! And you can drop the 2x
sortby using%in%for 146 bytes... \$\endgroup\$Dominic van Essen– Dominic van Essen2021年02月09日 11:55:16 +00:00Commented Feb 9, 2021 at 11:55 -
2\$\begingroup\$ Edit 3 (only check
%10for one factor, since each pair will always occur both ways around) is really smart! I've copied the approach to save a byte in my Husk answer - Thanks! \$\endgroup\$Dominic van Essen– Dominic van Essen2021年02月11日 08:08:51 +00:00Commented Feb 11, 2021 at 8:08 -
\$\begingroup\$ Very late comment, but this appears to return T for many non-vampiric inputs, 1023, 1056, 1089 \$\endgroup\$DialFrost– DialFrost2025年11月09日 01:18:29 +00:00Commented Nov 9 at 1:18
-
\$\begingroup\$ @DialFrost thanks! Looks like the
sorts were essential after all. \$\endgroup\$pajonk– pajonk2025年11月09日 20:05:43 +00:00Commented Nov 9 at 20:05
J, 43 bytes
".e.-@-:@#((0<[:".{:\)*[:*/".\)"1 i.@!@#A.]
Takes digits as a string.
For each permutation i.@!@#A.], use half the digit length -@-:@# to take non-overlapping infixes -- which slices into 2 halves -- and multiply those halves([:*/".\)"1. Then (to handle the trailing zero constraint) multiply that by (0<[:".{:\)*, which takes the last digits of each half, cats them, evaluates that as a two digit number, and checks if it's greater than 0.
Finally, check if the input number ". is an element of that list e..
-
\$\begingroup\$ I‘m not quite sure how the Footer works, how would I test this for a specific single input? \$\endgroup\$2021年02月08日 20:43:30 +00:00Commented Feb 8, 2021 at 20:43
-
\$\begingroup\$ @cairdcoinheringaahing Edited TIO for clarity. \$\endgroup\$Jonah– Jonah2021年02月08日 20:47:24 +00:00Commented Feb 8, 2021 at 20:47
-
1\$\begingroup\$ Looks like this fails for 153000 \$\endgroup\$2021年02月08日 21:08:55 +00:00Commented Feb 8, 2021 at 21:08
-
1\$\begingroup\$ Ugh, totally read over that the first time. Fixed now. Will regolf later. \$\endgroup\$Jonah– Jonah2021年02月08日 21:42:31 +00:00Commented Feb 8, 2021 at 21:42
JavaScript (Node.js), 88 bytes
f=(n,i=1)=>n<i*i*10&&i%10&&[...''+i+n/i].sort()+''==[...''+n].sort()||n*10>++i*i&&f(n,i)
[...''+i+n/i].sort()+''==[...''+n].sort()two factors use and only use digits in original number- if
n/iis not an integer, it converted into a string with.and not equals to another side which doesn't contain a..
- if
n<i*i*10,n*10>i*i: lengths of two numbers are the same.- It equip to
i/10 < n/i < i*10. And sincenhas even number of digits (as question mentioned),iandn/iwill have same number of digits.
- It equip to
i%10:iis not end with "0"
05AB1E, 14 bytes
œ2δäÅΔPQy€θĀà*
Outputs a non-negative integer as truthy and -1 as falsey.
Try it online or verify all test cases.
Explanation:
œ # Get all permutations of the (implicit) input
δ # Map over each permutation:
2 ä # And split it into two equal-sized halves
ÅΔ # Get the 0-based index of the first truthy result,
# or -1 if none are found:
P # Take the product of the two halves
Q # And check that it's equal to the (implicit) input
y # Push the halves again
€θ # Only leave the last digit of each halve
Ā # Check that it's not 0 (1 if [1-9]; 0 if 0)
à # Get the maximum of these two
* # Multiply the checks to verify both are truthy
# (after which the found index is output implicitly as result)
Ruby, (削除) 104 (削除ここまで) 96 bytes
It almost looks like a complete English sentence. Which probably is a bad thing for golfing.
->n{n.digits.permutation.any?{|s|a,b=s.each_slice(s.size/2).map{|x|x.join.to_i};a%10>0&&a*b==n}}
It can be written in 94 bytes with Ruby 2.7:
->n{n.digits.permutation.any?{|s|a,b=s.each_slice(s.size/2).map{_1.join.to_i};a%10>0&&a*b==n}}
Python 2, (削除) 105 (削除ここまで) (削除) 95 (削除ここまで) 94 bytes
-10 bytes thanks to Kevin Cruijssen! (switch to Python 2)
-1 byte thanks to dingledooper!
Very inefficient, segfaults for \$ n \gtrsim 18500\$ on TIO.
f=lambda n,k=2,S=sorted:k<n and(k%10>n%k<(len(`k`)==len(`n/k`)<S(`k`+`n/k`)==S(`n`)))|f(n,k+1)
Commented:
f=lambda n,k=2,S=sorted # recursive function
k<n # if k>=n return False
and # otherwise:
( ... ) # long boolean expression which is True if k and n//k make n a valid vampire number
k%10 # the last digit of k is
> n%k # larger than n%k which is
< ( ... ) # less than another boolean expression
# These two comparisons can only be satisfied with k%10>0<1
len(`k`) # the number of digits of k
== len(`n/k`) # is equal to the number of digits of n//k
< S(`k`+`n/k`) # and sorting the digits of k and n//k
== S(`n`) # results in the same list as sorting the digits of n
| f(n,k+1) # bitwise OR with result of the recursive call
-
1\$\begingroup\$ 97 bytes by switching to Python 2. \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2021年02月09日 09:40:56 +00:00Commented Feb 9, 2021 at 9:40
-
\$\begingroup\$ Reply to a deleted comment, but might be interesting to others: If
nhas divisorsjandn//jthat satisify all conditions, we will find this pair twice, since we iteratekfrom2ton. Eitherk=jork=n//jsatisfiesk%10>0and the remaining boolean expression isTruefor both values ofk. \$\endgroup\$ovs– ovs2021年02月09日 10:02:02 +00:00Commented Feb 9, 2021 at 10:02 -
1\$\begingroup\$ My comment above should be 95 bytes actually. The
//can also be/in Python 2. \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2021年02月09日 10:04:32 +00:00Commented Feb 9, 2021 at 10:04 -
1\$\begingroup\$ @KevinCruijssen thanks a lot! I was initially hesitant to use
`n`here because this doesn't work for long integers, but I guess restricting this tointis fine. As a bonus Python 2 seems to run out of stack size a little bit later ;). \$\endgroup\$ovs– ovs2021年02月09日 10:09:08 +00:00Commented Feb 9, 2021 at 10:09 -
1\$\begingroup\$ -1 byte since conditionals can be used on conflicting types in Python 2. \$\endgroup\$dingledooper– dingledooper2021年02月09日 19:32:23 +00:00Commented Feb 9, 2021 at 19:32
C (gcc), (削除) 286 (削除ここまで) (削除) 240 (削除ここまで) 218 bloody bytes (o,_,o)
-55 bloody bytes thanks to ceilingcat!
#define S(x,y)x^=y^=x^=y
o,a,b,c,r;f(int*_){c=atoi(_);v(o,_,o=strlen(_),r=0);r=r;}v(k,_,o,i)char*_;{--k?({for(v(k,_,o,0);i<k;v(k,_,o,!++i))S(_[k%2*i],_[k]);}):(a=atoi(_)/exp10(o/2))*(b=atoi(_+o/2))==c&&(a+b)%10?r=1:0;}
The input is a string and the output is either 1 or 0.
The core of the answer is the function v(), which implements Heap's algorithm to generate all the possible permutations of the input digits.
Here's an explanation of the code before some golfing:
#define S(x,y)x^=y^=x^=y // Macro used to swap digits
o, // length of the input string
a, // first half of one of the possible permutations of digits
b, // second half
r; // result: 1 if the input is a vampire number, 0 otherwise
char c[9]; // copy of the original input that will be compared with the permutations
f(_)char*_;{ // That's a simple function taking the input string
r=!strcpy(c,_); // initializing `r` to 0 and `c` to the input
v(o,_,o=strlen(_)); // calling v(o,_,o) while initializing `o` to the length of the input
r=r; // and returning rhe result `r`
}
v( // v() is a recursive function taking three parameters:
k, // the length of a substring of digits being permuted
_, // the whole current permutation
o, // the length of the whole permutation
i) // `i` is here just to avoid declaring `int i` inside the `for` loop
char*_;{
if(k-1){ // if `k` is not 1
v(k-1,_,o); // call v() to permute `k-1` digits
for(i=0;++i<k; // until `i` is less than `k`
v(k-1,_,o)) // call v() to permute `k-1` digit, but only after having
S(_[k%2?0:i-1],_[k-1]); // swapped _[k-1] with either _[0] or _[i-1]
}
else // else (i.e. if k == 1)
(a=atoi(_)/exp10(o/2)) // if `a` (getting the first half of the permutation, converted to integer)
*(b=atoi(_+o/2)) // multiplied by `b` (getting the second half)
==atoi(c) // equals the original input
&&(a+b)%10? // and only one between `a` and `b` has trailing zeros
r=1 // then the result is set to 1
:0; // otherwise do nothing, this permutation wasn't the right one
}
I tried other algorithms, but couldn't find a shorter one. I leave here the dumbest of the tries, which is a solution that doesn't solve the problem. It only finds most of the vampire numbers (probably).
-
\$\begingroup\$ Looks like 15300 is included in your output list, when it should return false \$\endgroup\$2021年02月09日 02:00:53 +00:00Commented Feb 9, 2021 at 2:00
-
\$\begingroup\$ @ceilingcat Wow thank you so much!! Using
exp10instead ofpowmade possible to cut off the(int)cast of the result. I own you these 5 more bytes. \$\endgroup\$anotherOne– anotherOne2021年02月09日 11:39:52 +00:00Commented Feb 9, 2021 at 11:39 -
1\$\begingroup\$ You are right, the commas would indeed fix the issue because they are sequence points. However this is codegolf and undefined behaviors are well accepted as long as the program shows the expected output in at least one compiler of your choice. \$\endgroup\$anotherOne– anotherOne2021年02月09日 21:19:24 +00:00Commented Feb 9, 2021 at 21:19
-
1\$\begingroup\$ @tgm1024--Monicawasmistreated if you wanted to swap without undefined behaviour the simplest solution is to just have an extra variable, z, and use z=x,x=y,y=z which adds 3 bytes (1 for longer macro and 2 for declaring z - since you cannot reuse an existing variable), compared to 4 for sequence points. but as noted UB is ok here. \$\endgroup\$Hans Olsson– Hans Olsson2021年02月11日 09:44:12 +00:00Commented Feb 11, 2021 at 9:44
-
1\$\begingroup\$ Davide, @HansOlsson, understood. Still feeling my way around this site. \$\endgroup\$tgm1024--Monica was mistreated– tgm1024--Monica was mistreated2021年02月11日 13:05:44 +00:00Commented Feb 11, 2021 at 13:05
Charcoal, 54 bytes
⊞υ⟦ωθ⟧FυFE§ι1⟦+§ι0κΦ§ι1−λν⟧⊞υκ⊙EΦυ¬⊟ιI⪪⊟ι⊘Lθ∧Σ%ιχ=θIΠι
Try it online! Link is to verbose version of code. Outputs a Charcoal boolean, i.e. - for vampire, nothing if not. Explanation:
⊞υ⟦ωθ⟧
Start a breadth-first enumeration of permutations of the input string.
Fυ
Loop over each partial permutation so far.
FE§ι1⟦+§ι0κΦ§ι1−λν⟧⊞υκ
Append each unused character to the permutation so far and push the result plus the remaining characters to the list.
⊙EΦυ¬⊟ι
Find whether any of the entries where all of the characters were used, ...
I⪪⊟ι⊘Lθ
... after being split into halves and cast to integer, ...
∧Σ%ιχ
... have a non-zero sum of the last digits, ...
=θIΠι
... and have the product of the halves resulting in the original string.
Python 2, (削除) 113 ... 112 (削除ここまで) 109 bytes
def f(n,s=sorted):x=s(`n`);l=10**(len(x)/2);return any(x==s(`i`+`n/i`)for i in range(l/10,l)if i%10and n%i<1)
-3 byte thanks Kevin Cruijssen
-
1\$\begingroup\$ The
//can be/for -3. It will do integer-division implicitly in Python 2 if both arguments are integers. (In Python 3+ you'll indeed have to use//.) \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2021年02月09日 10:06:08 +00:00Commented Feb 9, 2021 at 10:06
JavaScript (ES6), 93 bytes
Assumes that the input has an even number of digits. Returns a Boolean value.
f=(n,[...a]=n,p='')=>a[p.length]?a.some((v,i)=>f(n,a.filter(_=>i--),p+v)):p%10&&p*a.join``==n
JavaScript (ES6), 97 bytes
Expects the integer as a string. Returns 0 or 1.
f=(n,[...a]=n,p,q,k)=>a.some((v,i)=>f(n,a.filter(_=>i--),k?[p]+v:p,k?q:[q]+v,!k))|p%10*!(p*q^n|k)
Commented
f = ( // f is a recursive function taking:
n, // n = input integer, as a string
[...a] = n, // a[] = list of digits of n
p, q, // n is split into p and q (both initially undefined)
k // k is a flag, set on odd iterations
) => //
a.some((v, i) => // for each digit v at position i in a[]:
f( // do a recursive call:
n, // pass n unchanged
a.filter(_ => i--), // remove the i-th entry from a[]
k ? [p] + v : p, // append v to p if k is set
k ? q : [q] + v, // append v to q if k is not set
!k // toggle k
) // end of recursive call
) // end of some()
| // success if:
p % 10 * // the last digit of p is not 0,
!(p * q ^ n | k) // p * q = n and k is not set
Japt, 20 bytes
á mó f_dÌîmì ×ばつÃd\Uì
Try it online! or check all test cases (specifically the 15 vampire numbers and 153000)
Takes input as an array of digits. Input as an integer is one byte longer
Explanation:
á mó f_dÌîmì ×ばつÃd\Uì
á # Get all permutations of the input digits
mó # Divide each permutation into two groups of equal length
f_ Ã # Only keep ones where:
dÌ # At least one of the groups ends with a non-zero number
® Ã # For each remaining pair of groups:
mì # Treat each group of digits as an integer
×ばつ # Multiply those integers
d # Return true if at least one of the results...
\Uì # ... Is equal to the original number
Japt -x, (削除) 14 (削除ここまで) 12 bytes
Takes input as (削除) a digit array (削除ここまで) an integer string. Outputs 0 for falsey or a positive integer for truthy.
á ËÌÑ©Dó ×ばつ\U
á ËÌÑ©Dó ×ばつ\U :Implicit input of integer string U
á :Permutations
Ë :Map each D
Ì : Last character
Ñ : Multiplied by 2, to coerce to an integer (0 is falsey, everything else is truthy)
© : Logical AND with
Dó : Uninterleave D
×ばつ : Reduce by multiplication
\U : Is loosely equal to U?
Nekomata -e, (削除) 11 (削除ここまで) (削除) 9 (削除ここまで) (削除) 15 (削除ここまで) (削除) 14 (削除ここまで) 12 bytes
ŝaƊpy,p{lZ}↕ɗ=
-2 bytes thanks to alephalpha!
Explanation:
ŝaƊpy,ƆZɔ↕ɗ= | -e: Output whether a solution exists
-------------+-------------------------------------------------------
ŝ | Find two factors of input
aƊ | Digits of both factors
py | Are both lists the same length?
, | Join lists
ƆZɔ | Is the last digit non-zero?
↕ɗ= | Find a permutation that equals the digits of the input
-
\$\begingroup\$ Does this check that at least one partition doesn't end in
0? \$\endgroup\$Shaggy– Shaggy2025年11月10日 21:12:43 +00:00Commented Nov 10 at 21:12 -
\$\begingroup\$ @Shaggy it did not... I could have sworn that the false positive test case was accounted for, but apparently not. Fixed. \$\endgroup\$hakr14– hakr142025年11月10日 21:35:12 +00:00Commented Nov 10 at 21:35
-
1\$\begingroup\$ @Shaggy yes, I can! Thanks for the tip, I'll keep looking for more saves before I publish though \$\endgroup\$hakr14– hakr142025年11月10日 21:47:52 +00:00Commented Nov 10 at 21:47
-
1\$\begingroup\$ -2 bytes:
p{lZ}->ƆZɔ(\unsnoc \isNonzero \snoc). You can also use the-mflag to verify multiple test cases at the same time: Attempt This Online! \$\endgroup\$alephalpha– alephalpha2025年11月11日 01:57:17 +00:00Commented Nov 11 at 1:57 -
1\$\begingroup\$ @alephalpha I knew I was missing something! Thank you, and I will have to remember the
-mflag, that's really handy! \$\endgroup\$hakr14– hakr142025年11月11日 01:59:54 +00:00Commented Nov 11 at 1:59
-
1\$\begingroup\$ 14 bytes (My solution, forgot I could input as digits) \$\endgroup\$2021年02月08日 23:25:25 +00:00Commented Feb 8, 2021 at 23:25
-
1\$\begingroup\$ @cairdcoinheringaahing Wow, it's exactly the same, except for the fact that I'm a moron and didn't realize that I could just use
i. \$\endgroup\$Adamátor– Adamátor2021年02月08日 23:28:53 +00:00Commented Feb 8, 2021 at 23:28
Explore related questions
See similar questions with these tags.
n[]={1,2,6,0,1260}? Or is it too much? I am asking because I would need a for loop with two statements just to get 1260 from its digits (or the single digits from 1260) \$\endgroup\$