The Unholy numbers

Python (3), 137 131 bytes

def f(s):
 l=range(len(s))
 r=[min(i)for i in zip(*[[abs(j-i)for j in l]for i in l if s[i]in'46890'])]
 return sum(r)if r else'∞'

Results

>>> [f(i) for i in ['85587', '012321857', '157321', '04689']]
[3, 12, '∞', 0]

GNU APL, 27 bytes

{+/⌊/|(⍳⍴⍵)∘.-(⍵⍳⍕⍟788)~⍴⍵}

Try it online!

To try it out using the above link, IO must be set to 0 and the input is provided as a string. For example:

⎕IO←0
{+/⌊/|(⍳⍴⍵)∘.-(⍵⍳⍕⍟788)~⍴⍵}'017552857'

Explanation

{+/⌊/|(⍳⍴⍵)∘.-(⍵⍳⍕⍟788)~⍴⍵}  ⍝ Note: below explanation uses as example input 017552857 
{                            ⍝ dfn
                  ⍟788       ⍝ computes natural log of 788, which happens to be 6.66949809, containing only (and all) holy digits
                 ⍕           ⍝ Converts this number to a string
               ⍵⍳            ⍝ Finds the indexes of chars in the right argument ⍵ which are present in the computed decimal. Items not found map to the length of the list, e.g. '017552857'⍳'6.66949809' -> 9 9 9 9 9 9 9 6 0 9
                      ~⍴⍵    ⍝ Removed all non-found indexes from the list 9 9 9 9 9 9 9 6 0 9 -> 6 0
      (⍳⍴⍵)                  ⍝ List of ascending integers up the length of the argument ⍵: 0 1 2 3 4 5 6 7 8
           ∘.-               ⍝ Inner product of the ascending integers 0..8 minus the match indexes 6 0. Result is ¯6 0, ¯5 1, .., 2 8
     |                       ⍝ Absolute value of all elements
   ⌊/                        ⍝ Take the minimum of each pair to get the closest distance to a Holy number 0 1 2 3 2 1 0 1 2
 +/                          ⍝ Sum this list

The reason for choosing GNU APL is that handily it will return the internal representation of infinity, '∞', when calculating the minimum value of the empty list. Summing this still retains ∞, which is then returned.

⍟788 was a cheeky way to lose a byte. I ended up writing a program to brute force inputs to functions until I found a suitable result which contained only holy numbers. Brute force program below:

    (,(⍳99)∘.{∧/(~'12357'∊c),'04689'∊(c←⍕b←⍺÷⍵):(⍺,'f',⍵,'=',b,'|') ⋄ 0}⍳99)~0

In this case it sees if any values of ⍺÷⍵ in 0 < ⍺,⍵ < 100 meet the condition. I manually played around with the functions to test.

It's a bit of a shame that this challenge doesn't allow undefined behaviour for the infinity case or that Dyalog doesn't return an infinite data type instead of throwing an error, otherwise the following solution would work in Dyalog APL:

APL (Dyalog Unicode), 23 bytes

{+/⌊/|(⍳⍴⍵)∘.-⍸⍵∊⍕⍟788}

Try it online!


Pyth, 31 29 27 25 bytes

smhS.e?}b"04689"akd.n4zUz

Try it online: Demonstration or Test Suite

For each digit I compute the distances to each number. A distance is infinty, if the second digit is not holy. From these lists I take the minimal distance and sum it up.

Explanation:

smhS.e?}b"04689"akd.n4zUz  implicit: z = input string of numbers
 m                     Uz  map each d in [0, 1, ..., len(z)-1] to:
    .e                z      map each k (index), b (value) of b to:
                akd            absolute difference between k and d

      ?}b"04689"               if b in "04689" else
                   .n4         infinity
   S                           sort
  h                            take the first element (=minimum)
s                              print the sum