7
\$\begingroup\$

PROBLEM

For a list of numbers, list: Find the lowest possible integer, x, which is optimally close to the whole number even-harmonics of the values in list.

  • list has a length of n, and all of the values in list are <= 2000
  • x has a precision of 1.0 (integers only), and must be a value in the range [20, 100]
  • An even-harmonic is a number that is divisible by list an even number of times. 20 is an even harmonic of 80 (because 80/20=4) -- but an odd harmonic of 60 (because 60/20=3).
  • In this case, "optimally close" simply means to minimize the absolute cumulative remainder, relative to the nearest even harmonic of the input value(s).
    • Minimizing the absolute cumulative error takes priority over choosing the "lowest allowable value" for x.
    • Given list = [151, 450, 315] and a candidate guess of x=25 the absolute cumulative remainder is 0.64 because 25 goes into list [6.04, 18, 12.6] times, respectively. The nearest even-harmonics for each instance are [6, 18, 12].

EXAMPLE

list = [100, 300, 700, 1340]

  • x = 20 is a bad solution because it is an exact or almost-exact odd-harmonic of all of the values of list. The number 20 goes into list [5, 15, 35, 67] times, respectively (odd numbers = odd harmonics = the opposite of even-harmonics).
    • The absolute cumulative remainder is 4.0 in this case (which is the maximum possible error for this instance of list).
  • x = 25 is a good solution, but not the best, because it is a exact or almost-exact even-harmonic of all of the values of list. In this case, 25 is an exact even-harmonic in all cases except for 1340. The number 25 goes into list [4, 12, 20, 53.6] times, respectively (even numbers).
    • The absolute cumulative remainder is 0.4 in this case.

BONUS

Same prompt and problem, except x has a maximum precision of 0.1 (non-integer)

\$\endgroup\$
8
  • 1
    \$\begingroup\$ Why is x=25 the best solution, and not 2? All of 100, 300, 700, and 1340 are exactly divisible by 2 an even number of times. \$\endgroup\$
    – pxeger
    May 27 at 17:21
  • \$\begingroup\$ See bullet 2 in the problem statement. X must be in the range [20,100] \$\endgroup\$ May 27 at 17:22
  • \$\begingroup\$ Doesn't 20 go into 700 35 times? \$\endgroup\$
    – chunes
    May 27 at 17:39
  • \$\begingroup\$ Edited - thanks \$\endgroup\$ May 27 at 17:40
  • 3
    \$\begingroup\$ ...but the example you edited is the [100, 300, 700, 1340] one, for which it is not .213 \$\endgroup\$ May 27 at 18:30

12 Answers 12

5
\$\begingroup\$

Jelly, 16 bytes

÷Ɱȷ2Ḃ2_«Ɗ§Ụ>Ƈ19Ḣ

A monadic Link that accepts a list of integers and yields an integer.

Try it online!

How?

÷Ɱȷ2Ḃ2_«Ɗ§Ụ>Ƈ19Ḣ - Link: list of integers, A
  ȷ2             - 10^2 = 100
 Ɱ               - map across x in [1,100] with:
÷                -   A divided by x (vectorises)
    Ḃ            - mod 2 (vectorises)
        Ɗ        - last three links as a monad - f(v=that):
     2           -   two
      _          -   subtract v (vectorises)
       «         -   minimum with v (vectorises)
         §       - sums
          Ụ      - grade-up (one-based indices sorted by the value at that index)
            Ƈ    - filter keep if:
           > 19  -   greater than 19
               Ḣ - head
\$\endgroup\$
5
\$\begingroup\$

Factor + math.unicode, 83 78 77 bytes

[ 20 100 [a,b] [ v/n [ 2 mod dup 1 > 2 0 ? - abs ] map Σ ] with infimum-by ]

Try it online!

  • 20 100 [a,b] Create a range from 20 to 100, inclusive.
  • [ ... ] with infimum-by Find the number in the range that is smallest when [ ... ] is applied to it. with takes our input into the [ ... ] in such a way that it will be underneath each number in the range on the data stack.
  • v/n Divide each element in the input by the current number in the range.
  • [ ... ] map Σ Map each element to a new value with the [ ... ] quotation and then take the sum.
  • 2 mod dup 1 > 2 0 ? - abs Find the distance to the nearest even number.
\$\endgroup\$
4
\$\begingroup\$

JavaScript (ES6), 79 bytes

a=>(m=g=o=>x++>99?o:g(a.map(v=>e+=(v/=x)&1?1-v%1:v%1,e=0)|e>m?o:(m=e,x)))(x=19)

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Nicely done Arnauld! \$\endgroup\$ May 27 at 17:55
4
\$\begingroup\$

Python 3, 75 73 bytes

lambda l:min(range(20,101),key=lambda x:sum(min(a/x%2,-a/x%2)for a in l))

Try it online!

Saved 2 bytes thanks to Steffan!!!

Inputs a list of integers.
Returns the lowest even harmonic.

\$\endgroup\$
4
  • \$\begingroup\$ Nice! FYI this breaks if you feed it only a single list. Accepting multiple list inputs is not a requirement so you may be able to reduce this further by eliminating that functionality \$\endgroup\$ May 27 at 23:58
  • \$\begingroup\$ @AustinPrater Are you confusing my test harness (which works on multiple lists) with my solution (which inputs a single list)? The test harness doesn't break on a single list. It uses tuples so you need to put a comma after a single element (eg tuple of \$1\$: (1,)). \$\endgroup\$
    – Noodle9
    May 28 at 0:11
  • \$\begingroup\$ I see -- makes sense \$\endgroup\$ May 28 at 0:24
  • \$\begingroup\$ 73 \$\endgroup\$
    – Steffan
    May 28 at 0:37
4
\$\begingroup\$

Burlesque, 49 bytes

bc20 [email protected])td{?/{JR_2./2.*.-ab}ms}Z]ziq[~<m-]20.+

Try it online!

bc       # Repeat input list        
20 [email protected] # Range [20..100]
)td      # As doubles
{
 ?/      # Divide each
 {       # -- Find difference with nearest 2
  J      # Duplicate
  R_     # Round
  2./2.* # Closest multiple of 2
  .-     # Difference
  ab     # Abs
 }
 ms      # Map sum
}Z]      # Zip range with input and evaluate
zi       # Zip indices
q[~<m-]  # Index of minimum
20.+     # +20
\$\endgroup\$
4
\$\begingroup\$

R, 72 bytes

\(l,m=20:200,x=outer(l,m,`/`)%%2/2)m[order(colSums(abs(x-round(x))))[1]]

Attempt This Online!

\$\endgroup\$
4
\$\begingroup\$

Vyxal, 19 bytes

20₁ṡµ⁰$/:1%$∷1=+∑;h

Try it Online!

-2 bytes thanks to emanresu A, and another -3 by porting 05AB1E

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I have no idea how this works but here's 22 \$\endgroup\$
    – emanresu A
    May 28 at 2:53
3
\$\begingroup\$

Charcoal, 25 bytes

≔E⁸¹Σ↔⊖﹪⊕∕θ⁺²⁰ι²ηI⁺²⁰⌕η⌊η

Try it online! Link is to verbose version of code. Explanation:

  ⁸¹                        Literal integer `80`
 E                          Map over implicit range
          θ                 Input array
         ∕                  Vectorised divide
              ι             Current value
           ⁺                Plus
            ²⁰              Literal integer `20`
        ⊕                   Vectorised increment
       ﹪                    Vectorised modulo
               ²            Literal integer `2`
      ⊖                     Vectorised decrement
     ↔                      Vectorised absolute
    Σ                       Take the sum
≔               η           Store in variable
                        η   List of absolute cumulative errors
                       ⌊    Find the minimum
                     ⌕      Find index in
                      η     List of absolute cumulative errors
                  ⁺         Plus
                   ²⁰       Literal integer 20
                 I          Cast to string
                            Implicitly print
\$\endgroup\$
3
\$\begingroup\$

APL+WIN, 43 bytes

Prompts for vector of numbers in list

(m=⌊/m←+/¨|¨m-⌊¨m+1≤¨2|¨m←(⊂⎕)÷¨n)/n←19+⍳81

Try it online! Thanks to Dyalog Classic

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

C# (Visual C# Interactive Compiler), 80 bytes

a=>Enumerable.Range(20,81).OrderBy(x=>a.Sum(k=>Math.Min(2-k/x%2,k/x%2))).First()

Try it online!

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

05AB1E, 15 bytes

20тŸΣ/D1%sÉ+O}н

Try it online or verify both test cases.

Explanation:

20тŸ         # Push a list in the range [20,100]
    Σ        # Sort it by:
     /       #  Divide the (implicit) input-list by this value
      D      #  Duplicate the decimal values
       1%    #  Modulo-1 to only keep the decimal portion
      s      #  Swap so the entire values are at the top again
       É     #  Check which ones are odd (ignoring the decimal portions)
         +   #  Add the values at the same positions together
          O  #  Sum this list together
    }н       # After the sort-by, keep just the first element
             # (so `Σ...}н` basically acted as a minimum-by builtin)
             # (which is output implicitly as result)
\$\endgroup\$
2
\$\begingroup\$

C, 122 bytes

i,j,k;f(n,m)int*n;{float a=m,b,c;for(i=19;99/i++;k=b<a?a=b,i:k)for(j=b=0;j<m;b+=fabs(c-rint(c))*2)c=n[j++]/2./i;return k;}

Try it online!

Bonus:

C, 134 bytes

i,j,k;float f(n,m)int*n;{float a=m,b,c;for(i=199;999/i++;k=b<a?a=b,i:k)for(j=b=0;j<m;b+=fabs(c-rint(c))*2)c=n[j++]/.2/i;return k/10.;}

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.