20
\$\begingroup\$

We haven't had any nice, easy challenges in a while, so here we go.

Given a list of integers each greater than \$0\$ and an index as input, output the percentage of the item at the given index of the total sum of the list.

Output should be whatever the natural representation for floats/integers is in your language (unary, decimal, Church numerals etc.). If you choose to round the output in any way, it must have at minimum 2 decimal places (when reasonable. \$1.2\$ doesn't need to be rounded, but \$1.20\$ is also perfectly acceptable).

Indexes can be either 1-indexed or 0-indexed, and will always be within the bounds of the array.

This is , so the shortest code in bytes wins!

Examples

Using 1-indexed and rounded to 2 d.p

list, index                    =>         output
[1, 2, 3, 4, 5], 5             => 5 / 15    => 33.33
[7, 3, 19], 1                  => 7 / 29    => 24.14
[1, 1, 1, 1, 1, 1, 1, 1, 1], 6 => 1 / 9     => 11.11
[20, 176, 194, 2017, 3], 1     => 20 / 2410 => 0.83
[712], 1                       => 712 / 712 => 100

Or, as three lists:

[[1, 2, 3, 4, 5], [7, 3, 19], [1, 1, 1, 1, 1, 1, 1, 1, 1], [20, 176, 194, 2017, 3], [712]]
[5, 1, 6, 1, 1]
[33.33, 24.14, 11.11, 0.83, 100]
\$\endgroup\$
10
  • \$\begingroup\$ Sandbox post (now deleted) \$\endgroup\$ Commented Sep 29, 2019 at 0:04
  • 3
    \$\begingroup\$ how exactly can non-integers be output as unary / church numerals? \$\endgroup\$
    – Doorknob
    Commented Sep 29, 2019 at 3:25
  • 1
    \$\begingroup\$ @Doorknob Maybe a unary number, the dot, and another unary number? \$\endgroup\$ Commented Sep 29, 2019 at 5:32
  • \$\begingroup\$ Since the output can be rounded to two decimal places, it might also be permissible to output rounded times 100? \$\endgroup\$ Commented Sep 29, 2019 at 6:10
  • 1
    \$\begingroup\$ test case 4 should be 20/2410 \$\endgroup\$
    – att
    Commented Sep 29, 2019 at 8:31

54 Answers 54

1
2
1
\$\begingroup\$

Ruby, 25 23 21 bytes

->a,i{1e2*a[i]/a.sum}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Perl 6, 21 bytes

{100*@^a[$^b]/@a.sum}

Try it online!

The simple solution, since I can't use curried parameters with the $b parameter being indexed. A funner solution that doesn't have to handle two parameters by using the rotate function instead:

{100*.[0]/.sum}o&rotate

Try it online!

But it is unfortunately two bytes longer

\$\endgroup\$
1
\$\begingroup\$

Octave, 21 bytes

@(a,n)a(n)/sum(a)*100

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Icon, 53 bytes

procedure f(L,i)
s:=0;s+:=!L&\z
return 1e2*L[i]/s
end

Try it online!

The only interesting thing here is finding the sum. Icon was one of the first languages to have generators. ! generates all the values of the list L that are accumulated to s. Normally we need to write every s+:=!L, but I used backtracking with &\z, which checks if the non-existent z variable is non-null, which is not, and extracts the next value from the list until exhaustion.

\$\endgroup\$
1
\$\begingroup\$

Batch, 111 bytes

@shift
@set s=%*
@call set/as=%s: =+%-%0,s=(%%%0*10000+s/2)/s,h=s%%%%10,t=s/10%%%%10,s/=100
@echo %s%.%t%%h%

Takes input as index and list as command-line arguments. Note: Only works for index values from 1 to 9 due to limitations of Batch; a 0-indexed version could be written which would be able to index the first 10 elements. Explanation:

@shift

Shift the index to %0 and the list to %1...%9 (or less). Note however that Batch's shift does not affect %*.

@set s=%*

Get all of the parameters, space separated.

@call set/as=%s: =+%-%0,s=(%%%0*10000+s/2)/s,h=s%%%%10,t=s/10%%%%10,s/=100

Change the spaces to +s and evaluate arithmetically, thus taking the sum, but subtract the index. Then index into the list, multiply by 10000, add half of the sum, and divide by the sum. Finally perform divmod by 10 twice to generate the decimal places. (The % arithmetic operator has special meaning in Batch and normally needs to be doubled but the call then requires a further doubling.)

@echo %s%.%t%%h%

Output the result and the decimal places.

\$\endgroup\$
1
\$\begingroup\$

Swift, 60 bytes

{(n:[Int],i)->Float in
1e2*Float(n[i])/Float(n.reduce(0,+))}

Try it online!

I picked Swift to participate and bumped into its type sensitivity !

\$\endgroup\$
1
\$\begingroup\$

Racket, 81 43 bytes

Accepts a list and index. Outputs rationals (default for division in Racket). Big thanks to Galen Ivanov for finding the apply function. Still learning as I go :) .

(λ(l i)(*(/(list-ref l i)(apply + l))100))

Try it online!

\$\endgroup\$
5
  • 1
    \$\begingroup\$ To my understand, #lang racket is not counted into bytes if submission is a function. \$\endgroup\$
    – tsh
    Commented Sep 30, 2019 at 6:33
  • \$\begingroup\$ I think tsh is right. You can make it work in TIO by assigning the lambda to a variable. Since this is code-golf, you need to remove all the whitespaces like this for 60 bytes \$\endgroup\$ Commented Sep 30, 2019 at 6:39
  • \$\begingroup\$ (foldl (λ (a b) (+ a b)) 0 l) -> (apply + l) for 44 bytes \$\endgroup\$ Commented Sep 30, 2019 at 6:44
  • 1
    \$\begingroup\$ @GalenIvanov The last ) is matched to (define and is not a part of function. So it should not be included too. \$\endgroup\$
    – tsh
    Commented Sep 30, 2019 at 6:48
  • \$\begingroup\$ @tsh Yes, of course! I forgot to move it to the footer. So it is 43 bytes \$\endgroup\$ Commented Sep 30, 2019 at 6:54
1
\$\begingroup\$

AWK, 43 40 bytes

{s+=a[NR]=$1}END{print 100*a[$1]/(s-$1)}

Try it online!

-3 bytes thanks to CowsQuack

Takes the index as the last line of input

\$\endgroup\$
6
  • \$\begingroup\$ I saw you mention in chat for more test cases, here's a bash wrapper. \$\endgroup\$ Commented Sep 29, 2019 at 20:32
  • \$\begingroup\$ @GammaFunction Thanks! I had no idea you could write to the file system in TIO. \$\endgroup\$
    – Jonah
    Commented Sep 29, 2019 at 21:04
  • \$\begingroup\$ @GammaFunction What's the reason we need the space and single quotes around EOF there to make it work? \$\endgroup\$
    – Jonah
    Commented Sep 29, 2019 at 21:12
  • 1
    \$\begingroup\$ Single quotes prevent $expansions from happening in the heredoc. The space does nothing either way \$\endgroup\$ Commented Sep 29, 2019 at 21:16
  • 1
    \$\begingroup\$ {s+=a[NR]=$1} shaves 3 bytes \$\endgroup\$
    – user41805
    Commented Sep 30, 2019 at 6:41
1
\$\begingroup\$

T-SQL 2008, 41 bytes

To find the row number equal to the index:

A division of index and row number multiplied with division of row number and index, if both results are 1, index and row are the same because both are above 0 and integer division round down. This saves 1 byte compared to using IIF

a - value

b - row number

Using table variable as input. 1-indexed

SELECT max(b/@*(@/b)*a*100)/sum(a)FROM @x

Try it online

\$\endgroup\$
1
\$\begingroup\$

Julia 1.0, 21 bytes

f(l,i)=100l[i]/sum(l)

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Bash, 77 75 73 72 80 76 75 bytes

a=($@)
((b=10000*${a[$1]}/(${@/%/+}-$1),b<10))
echo $[b/100].${?/1}$[b%100]

Try it online!

+8 bytes thanks to GammaFunction, who found a bug with large numbers

-5 bytes thanks to GammaFunction, who golfed his original bug fix

\$\endgroup\$
2
  • \$\begingroup\$ Ah, nice catch. Ty! \$\endgroup\$
    – Jonah
    Commented Sep 29, 2019 at 20:56
  • 1
    \$\begingroup\$ Whoops, saved one more. I don't think bash is going to let me be any more clever than this, though \$\endgroup\$ Commented Sep 29, 2019 at 21:28
1
\$\begingroup\$

Stax, 7 bytes

â└╡Æå'W

Run and debug it at staxlang.xyz!

0-indexed. Requires at least one item in the input list to be of the form N.0 rather than simply N. Replacing / in the unpacked version with :_ gets around this restriction at the cost of one byte.

Unpacked (8 bytes) and explanation:

@AJ*x|+/    Index atop the stack, with the list beneath
@           Element at index...
 AJ*        Times 100
    x|+     Sum of list
       /    Divide
\$\endgroup\$
1
\$\begingroup\$

k4, 14 bytes

{%+/x%100*x y}

can save 1 byte from @Galen Ivanov's solution (in oK) as % is inverse operation in k4 as opposed to square root

\$\endgroup\$
1
\$\begingroup\$

Clojure, 40 bytes

(fn[a b](* 1e2(/(nth a b)(apply + a))))

Try it online!

It's nice to know about the 1e2 trick. :-)

\$\endgroup\$
1
\$\begingroup\$

Arturo, 23 bytes

$[a,i][100*a\[i]//∑a]

Try it

\$\endgroup\$
1
\$\begingroup\$

PowerShell Core, 39 bytes

param($a,$i)$a[$i]/($a-join'+'|iex)*1e2

Try it online!

Uses 0 indexed input and doesn't do rounding

\$\endgroup\$
1
\$\begingroup\$

Pyt, 10 bytes

Đ←⦋⇹Ʃᵮ/2ᴇ*

Try it online!

Zero-based indexing. Takes the array, then the index

Đ                 implicit input; Đuplicate
 ←                get input
  ⦋               get element at index
   ⇹              swap top two items on stack
    Ʃ             get Ʃum
     ᵮ            cast to ᵮloat
      /           divide
       2ᴇ*        multiply by 100; implicit print
\$\endgroup\$
1
\$\begingroup\$

Itr, 11 bytes

#ä#@áS/100*

zero-indexed, outputs a fraction

online Interpreter

7 bytes to output the proportion as a fraction:

#ä#@áS/

Explanation

#           ; read the first input
 ä          ; duplicate it
  #         ; read the second input
   @        ; get the element at that index in the first input
    á       ; swap the two elements
     S      ; sum up the array
      /     ; divide the element by the sum
       100* ; convert the result to percent
            ; implicit output

Itr, 14 bytes

#ä#@áS/0e100**

outputs the result as a float

\$\endgroup\$
1
\$\begingroup\$

Rust, 36 bytes

|v,i|v[i]*100./v.iter().sum::<f32>()

0-indexed, assuming integers cast to floats before the function call

Rust Playground

\$\endgroup\$
0
\$\begingroup\$

Canvas, 8 bytes

@;∑÷AA××

Try it here!

Uses 1-indexing.

The last half just multiplies by 100, so 4 bytes can be saved if percentage over interval [0,1] is allowed as opposed to percentage over interval [0,100].


Explanation of example run: list = [1, 2, 3, 4, 5], index = 5.

Stack Visualization                 | Executed Instruction | Explanation
------------------------------------+----------------------+-----------------------------------------------------------------------------
..., [1,2,3,4,5], 5, [1,2,3,4,5]    | (program start)      | Canvas starts with the stack populated with the inputs repeating infinitely
..., [1,2,3,4,5], 5                 | @, get item         | @NA gets the Nth item of A
..., 5, [1,2,3,4,5]                 | ;, swap two ToS     | Swaps the position of the two top items in the stack
..., 5, 15                          | ∑, sum               | Sums all items in an array
..., 0.33333333333333333333         | ÷, divide            | Divides the two top items in the stack
..., 0.33333333333333333333, 10     | A, push 10          | Pushes 10 to the stack
..., 0.33333333333333333333, 10, 10 | A, push 10          | "                    "
..., 0.33333333333333333333, 100    | ×, multiply          | Multiplies the two top items in the stack
..., 33.333333333333333333          | ×, multiply          | "                                       "
...                                 | (end of program)     | Pop and print ToS
\$\endgroup\$
0
\$\begingroup\$

Forth (gforth), 61 bytes

: f 8 * over + f@ 0e swap 0 do dup f@ f+ 8 + loop f/ 1e2 f* ;

Try it online!

It's way too painful to work with arrays in Forth...

A function that takes three items (array length, array start address, index; rightmost being the top) from the main stack, and gives the answer on the FP stack. The array contains floating-point values.

How it works

: f ( len addr idx -- F: ans )
  8 * over + ( len addr addr[idx] ) \ compute the address for the item
  f@ 0e ( len addr F:x F:sum )      \ fetch the float at addr[idx] and push 0 on FP stack
  swap 0 do ( addr F:x F:sum )      \ repeat len times..
    dup f@ f+                       \   fetch the float at addr, add it to the sum
    8 +                             \   increment the addr by one cell
  loop                              \ end loop
  f/ 1e2 f*                         \ compute x / sum * 100
;
\$\endgroup\$
0
\$\begingroup\$

Vyxal, 6 bytes

₌i∑/₁*

Try it Online!

Another 6 byter joins the fray. Takes index then list. 0-indexed

Explained

₌i∑/₁*
₌i∑     # Push list[index], sum(list)
   /    # ^ / ^
    ₁*  # times 100
\$\endgroup\$
0
\$\begingroup\$

Thunno, \$ 9 \log_{256}(96) \approx \$ 7.41 bytes

AHz1S/Z2*

Attempt This Online!

Uses 1-indexing. Change AH to AI for 0-indexing.

Explanation

AHz1S/Z2*  # Implicit input
AH         # Index into the list
  z1S      # Sum the list
     /     # Divide
      Z2*  # Multiply by 10**2
\$\endgroup\$
0
\$\begingroup\$

Thunno 2, 6 bytes

i$S/ɦ×

Try it online!

0-indexed. Change i to İ for 1-indexing.

Explanation

i$S/ɦ×  # Implicit input
i       # Index in
 $      # Push the first input again
  S     # Take the sum
   /    # Divide
    ɦ×  # Multiply by 100
        # Implicit output
\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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