# The Holier Numbers

As we learned from The Holy Numbers, there are 5 holy digits (0, 4, 6, 8, 9), and positive integers consisting solely of those digits are holy. Additionally, the holiness of a number is the sum of the holes in the number (+2 for every 0 or 8, and +1 otherwise).

Now, there is an additional property to take into consideration, to truly and accurately represent the holiness of a number. You see, it's not just the number of holes in the digit that matters, but also where in the number it occurs.

Consider the number 88. By our old rules, it would have a holiness of 4. But that's hardly fair! The 8 on the left is doing more work than the other 8 - 10 times the work! It should be rewarded for its work. We will reward it with extra holiness points equal to the total holiness of all the digits to its right (including the extra holiness points granted by this rule to the digits on its right), minus 1.

Here are more examples to take into consideration:

Number: 8080
Digital holiness: (2 + 7 - 1) + (2 + 3 - 1) + (2 + 1 - 1) + (2 + 0 - 1)
Total holiness: 15

Number: 68904
Digital holiness: (1 + 5 - 1) + (2 + 2 - 1) + (1 + 1 - 1) + (2 + 0 - 1) + (1 + 0 - 1)
Total holiness: 10


All of the digits are appropriately rewarded for their work with extra holiness, and all is well. We shall call this property "enhanced holarity".

In the great language Python, an algorithm for calculating enhanced holarity might look something like this:

# assumes n is a holy number
def enhanced_holarity(n):
if n < 10:
return 1 if n in [0, 8] else 0
else:
digits = list(map(int,str(n)[::-1]))
res = []
for i,x in enumerate(digits):
res.append(enhanced_holarity(x))
if i > 0:
res[i] += sum(res[:i])
return sum(res)


## The Challenge

Given an integer n > 0, output the first n Holy Numbers, sorted by ascending enhanced holarity, using numeric value as a tiebreaker. You may assume that the input and output will be no greater than the maximum representable integer in your language or 2^64 - 1, whichever is less.

For reference, here are some test cases (input, followed by output):

25
4, 6, 9, 44, 46, 49, 64, 66, 69, 94, 96, 99, 0, 8, 84, 86, 89, 40, 48, 60, 68, 90, 98, 80, 88

100
4, 6, 9, 44, 46, 49, 64, 66, 69, 94, 96, 99, 444, 446, 449, 464, 466, 469, 494, 496, 499, 644, 646, 649, 664, 666, 669, 694, 696, 699, 0, 8, 84, 86, 89, 844, 846, 849, 864, 866, 869, 894, 896, 899, 40, 48, 60, 68, 90, 98, 404, 406, 409, 484, 486, 489, 604, 606, 609, 684, 686, 689, 80, 88, 804, 806, 809, 884, 886, 889, 440, 448, 460, 468, 490, 498, 640, 648, 660, 668, 690, 698, 840, 848, 860, 868, 890, 898, 400, 408, 480, 488, 600, 608, 680, 688, 800, 808, 880, 888

200
4, 6, 9, 44, 46, 49, 64, 66, 69, 94, 96, 99, 444, 446, 449, 464, 466, 469, 494, 496, 499, 644, 646, 649, 664, 666, 669, 694, 696, 699, 944, 946, 949, 964, 966, 969, 994, 996, 999, 4444, 4446, 4449, 4464, 4466, 4469, 4494, 4496, 4499, 4644, 4646, 4649, 4664, 4666, 4669, 4694, 4696, 4699, 0, 8, 84, 86, 89, 844, 846, 849, 864, 866, 869, 894, 896, 899, 40, 48, 60, 68, 90, 98, 404, 406, 409, 484, 486, 489, 604, 606, 609, 684, 686, 689, 904, 906, 909, 984, 986, 989, 4044, 4046, 4049, 4064, 4066, 4069, 4094, 4096, 4099, 80, 88, 804, 806, 809, 884, 886, 889, 440, 448, 460, 468, 490, 498, 640, 648, 660, 668, 690, 698, 940, 948, 960, 968, 990, 998, 4404, 4406, 4409, 4484, 4486, 4489, 4604, 4606, 4609, 4684, 4686, 4689, 840, 848, 860, 868, 890, 898, 400, 408, 480, 488, 600, 608, 680, 688, 900, 908, 980, 988, 4004, 4006, 4009, 4084, 4086, 4089, 800, 808, 880, 888, 4440, 4448, 4460, 4468, 4490, 4498, 4640, 4648, 4660, 4668, 4690, 4698, 4040, 4048, 4060, 4068, 4090, 4098, 4400, 4408, 4480, 4488, 4600, 4608, 4680, 4688, 4000, 4008, 4080, 4088

• This hole idea is holarious. Feb 24, 2016 at 8:32
• What do you mean by "output will be no greater than..."? As in the output won't have any number greater than 2^64 - 1? If that's the case it's probably worth figuring out which input first generates such numbers, so people can test their answers. Feb 24, 2016 at 14:34
• @FryAmTheEggman No greater than means less than or equal to. I'll update the post with some maximums for various integer sizes.
– user45941
Feb 24, 2016 at 20:48
• Your python code does not work for 6, it produces a holines of 0.
– shrx
Feb 25, 2016 at 12:43

## Lua, 317 Bytes

I had some troubles doing this, some things in Lua don't work as I think it does. I will have to try and play with them if I want to golf this down. You can test lua online by replacing arg[1] by the number of elements you want :).

function f(y)h=0(y..''):reverse():gsub(".",function(c)h=c:find("[08]")and 1+h or h end)return h end
x,a=0,{}while(#a<arg[1]+0)do a[#a+1],x=(x..''):find("^[04689]*$")and x or nil,x+1 end for i=1,#a do m=1 for j=1,#a do x=a[m]m=(f(x)~=f(a[j])and f(x)>f(a[j])or x>a[j])and j or m end end print(a[m])table.remove(a,m)end  ### Ungolfed and explanations function f(y) -- function returning the enhanced holiness of a holy number h=0 -- h is the cumulated holyness of processed digits (y..''):reverse() -- reverse the digits in y :gsub(".",function(c) -- iterate over each digits h=c:find("[08]")and 1+h or h -- ternary based on the digit being [08] or [469] end) return h -- return h end x,a=0,{} -- initialise a counter, and the array of holy numbers while(#a<arg[1]+0) -- iterate until we have n holy numbers do a[#a+1]=(x..'') :find("^[04689]*$")         -- if we can't find an unholy digit
and x or nil         -- insert x into a
x=x+1                           -- increment x anyway
end

for i=1,#a                        -- iterate n times(current size of a)
do
m=1                             -- m is the index of the lowest value
for j=1,#a                      -- iterate over a
do
x=a[m]                        -- x is shorter to write than a[m]
m=(f(x)~=f(a[j])              -- nested ternaries, translated in
and f(x)>f(a[j])          -- nested if below
or x>a[j])and j or m
end
print(a[m])                     -- output a[m]
table.remove(a,m)               -- remove it from the table a
end


The nested ternaries used for the new value of m can be translated in nested ifs as:

if(f(a[m])~=f(a[j])) then         -- if a[m] and a[j] don't have the same holyness
if(f(a[m])>f(a[j])) then m=j end-- compare by holyness
else
if(a[m]>a[j]) then m=j end      -- else, compare by numeric value


Also, I would have loved to replace the nested for by using table.sort, but, for a reason I don't know, the following doesn't work despite not producing an infinite loop or crushing the sort function.

table.sort(a,function(i,j)
return f(i)~=f(j)
and f(i)>f(j)
or i>j
end)


# Python 2, 138 122 bytes

This looks for holy numbers up to 5N for an input N, which is ridiculously slow:

e=lambda s:s and(s[0]in'08')+e(s[1:])*2or 0
lambda N:sorted([xfor x in range(5**N)if set(x)<=set('04689')][:N],key=e)


Here the limit is 5N2, and you can actually run the test cases, at the cost of a single byte:

e=lambda s:s and(s[0]in'08')+e(s[1:])*2or 0
lambda N:sorted([xfor x in range(5*N*N)if set(x)<=set('04689')][:N],key=e)


The first snippet is valid, as 5N ≥ 5N2 for all positive integers N.

• Oh, wait, I missed something.. Too tired for this. Feb 25, 2016 at 21:40

## JavaScript (ES6), 166 165 bytes

f=n=>[...Array(n)].map((_,i)=>i.toString(5)).sort((a,b)=>e(a)-e(b),e=n=>'0b'+[...n.replace(/./g,c=>'10010'[c])].reverse().join).map(n=>+n.replace(/./g,c=>"04689"[c]))


Edit: Saved 1 byte by returning an array of strings.

Ungolfed:

function base5_to_extended_holiness_binary(c) {
return "10010"[c];
}
function extended_holiness(n) {
var binary = n.toString(5).replace(/./g, base5_to_extended_holiness_binary);
binary = s.split("").reverse().join("");
return parseInt(s, 2);
}
function extended_holiness_sort(a, b) {
return extended_holiness(a) - extended_holiness(b);
}
function base5_to_holy_number(c) {
return "04689"[c];
}
function list_by_extended_holiness(n) {
var array = new Array(n);
for (var i = 0; i < n; i++)
array[i] = i;
array = array.sort(extended_holiness_sort);
for (var i = 0; i < n; i++)
array[i] = parseInt(array[i].toString(5).replace(/./g, base5_to_holy_number);
return array;
}