Tỷ lệ phần trăm


21

Viết hàm lấy trong danh sách các số nguyên dương và trả về danh sách các số nguyên xấp xỉ phần trăm của tổng số cho số nguyên tương ứng ở cùng vị trí.

Tất cả các số nguyên trong danh sách trả về phải cộng chính xác tới 100. Bạn có thể giả sử tổng số nguyên được truyền vào lớn hơn 0. Cách bạn muốn làm tròn hoặc cắt các số thập phân tùy thuộc vào bạn miễn là bất kỳ số nguyên kết quả nào được trả về theo tỷ lệ phần trăm bị tắt bởi không quá 1 theo một trong hai hướng.

p([1,0,2])      ->  [33,0,67] or [34,0,66]
p([1000,1000])  ->  [50,50]
p([1,1,2,4])    ->  [12,12,25,51] or [13,12,25,50] or [12,13,25,50] or [12,12,26,50]
p([0,0,0,5,0])  ->  [0,0,0,100,0]

Đây là , vì vậy mã ngắn nhất tính bằng byte sẽ thắng!


Thuật toán của chúng ta phải có tính quyết định? Nó phải luôn luôn chấm dứt trong một thời gian giới hạn?
lirtosiast

Chúng tôi đã có một số vấn đề làm tròn tương tự nhưng tổng quát hơn
edc65

1
Tôi đề nghị bạn thêm một trường hợp thử nghiệm : p([2,2,2,2,2,3]). Nó có nhiều câu trả lời hợp pháp có thể, nhưng không phải tất cả đều 2có thể được ánh xạ tới cùng một giá trị. Điều này giúp loại bỏ nhiều thuật toán quá đơn giản hoạt động trên tất cả các trường hợp thử nghiệm trước đó bởi vì làm tròn không quá tệ.
Sophia Lechner

4
Có thể p([1000,1000]) -> [49,51]không?
l4m2

1
@ l4m2 Có vẻ sai, nhưng cả hai kết quả đều giảm đi 1 và không còn nữa, vì vậy nó tuân theo thông số kỹ thuật
edc65

Câu trả lời:


20

APL Dyalog, 21 19 16 byte

+\⍣¯1∘⌊100×+\÷+/

Trên đây là một chuyến tàu tương đương với

{+\⍣¯1⌊100×+\⍵÷+/⍵}

Hãy thử trực tuyến.

Làm thế nào nó hoạt động

                 ⍝ Sample input: 1 1 2 4
           +\    ⍝ Cumulative sum of input. (1 2 4 8)
              +/ ⍝ Sum of input. (8)
             ÷   ⍝ Divide the first result by the second. (0.125 0.25 0.5 1)
       100×      ⍝ Multiply each quotient by 100. (12.5 25 50 100)
      ⌊          ⍝ Round the products down to the nearest integer... (12 25 50 100)
     ∘           ⍝ and ...
  ⍣¯1            ⍝ apply the inverse of...
+\               ⍝ the cumulative sum. (12 13 25 50)

9
Giá như Fermat có thể lấy bài học golf từ bạn.
TessellatingHeckler

1
@TessellatingHeckler Tôi thấy những gì bạn đã làm ở đó. Có lẽ sau đó anh ta có đủ chỗ trong lề cho bằng chứng của mình. :)
mbomb007

14

TI-BASIC, 26 23 16 byte

Đối với máy tính sê-ri TI-83 + / 84 +.

ΔList(augment({0},int(cumSum(ᴇ2Ans/sum(Ans

Cảm ơn @Dennis cho một thuật toán đẹp! Chúng tôi lấy tổng số tích lũy của danh sách sau khi chuyển đổi thành phần trăm, sau đó lên sàn, giải quyết số 0 ở phía trước và lấy sự khác biệt. ᴇ2ngắn hơn một byte so với 100.

Tại cùng một số byte là:

ΔList(augment({0},int(cumSum(Ans/sum(Ans%

Sự thật thú vị: %là một mã thông báo hai byte nhân một số với 0,01, nhưng không có cách nào để nhập nó vào máy tính! Bạn cần chỉnh sửa nguồn bên ngoài hoặc sử dụng chương trình lắp ráp.

Mã cũ:

int(ᴇ2Ans/sum(Ans
Ans+(ᴇ2-sum(Ans)≥cumSum(1 or Ans

Dòng đầu tiên tính toán tất cả các phần trăm được thả nổi, sau đó dòng thứ hai thêm 1 vào các Nphần tử đầu tiên , trong đó Ntỷ lệ phần trăm còn lại. cumSum(là viết tắt của "tổng tích lũy".

Ví dụ với {1,1,2,4}:

          sum(Ans                  ; 8
int(ᴇ2Ans/                         ; {12,12,25,50}

                        1 or Ans   ; {1,1,1,1}
                 cumSum(           ; {1,2,3,4}
     ᴇ2-sum(Ans)                   ; 1
                ≥                  ; {1,0,0,0}
Ans+                               ; {13,12,25,50}

Chúng tôi sẽ không có N>dim([list], bởi vì không có phần trăm nào giảm hơn 1 trên sàn.


Không chắc bạn đếm số byte ở đây như thế nào, nó trông dài hơn 23 so với tôi
David Arenburg

@DavidArenburg Đây chỉ là hình thức dễ đọc của con người. Tất cả các thẻ ( int(, sum(, Ans, vv) chỉ chiếm một byte.
Dennis

4
+1 Đây là một trong những sân golf TI-BASIC ấn tượng nhất tôi từng thấy trên trang web này.
PhiNotPi

Thomas câu trả lời này là tuyệt đẹp!
DaveAlger

Bạn có chắc chắn không có cách nào để nhập %biểu tượng? Tôi đã nghĩ rằng nó có thể được tìm thấy trong danh mục biểu tượng ... Ngoài ra, tôi nên lấy TI-84 + Silver của mình. Tôi đã không sử dụng nó trong một thời gian. Block Dude thật tuyệt vời.
mbomb007

7

CJam, 25 23 22 byte

{_:e2\:+f/_:+100-Xb.+}

Cảm ơn @ Sp3000 cho 25 → 24.

Hãy thử trực tuyến.

Làm thế nào nó hoạt động

_                   e# Push a copy of the input.
 :e2                e# Apply e2 to each integer, i.e., multiply by 100.
    \               e# Swap the result with the original.
     :+             e# Add all integers from input.
       f/           e# Divide the product by the sum. (integer division)
        _:+         e# Push the sum of copy.
           100-     e# Subtract 100. Let's call the result d.
               Xb   e# Convert to base 1, i.e., push an array of |d| 1's.
                 .+ e# Vectorized sum; increment the first |d| integers.

5

Toán học, 41 byte

(s=Floor[100#/Tr@#];s[[;;100-Tr@s]]++;s)&

Đợi đã, chuyện gì xảy ra ở đây?
xem

@Seeq Thuật toán giống như mã cũ trong câu trả lời TI-BASIC. Nó tính toán tất cả các phần trăm được thả nổi, sau đó thêm 1 vào các Nphần tử đầu tiên , trong đó Nphần trăm còn lại.
alephalpha

5

J (8.04 beta) , 59 byte (30 byte bị đánh cắp)

Cổng J 30 ký tự của câu trả lời APL của Dennis :

    f=.3 :'+/\^:_1<.100*(+/\%+/)y'

    f 1 1 2 4
12 13 25 50

Câu trả lời 59 byte, tốt nhất tôi có thể tự làm:

f=.3 :0
p=.<.100*y%+/y
r=.100-+/p
p+((r$1),(#p-r)$0)/:\:p
)

(Dựa trên phần còn lại phải chuyển đến các giá trị cao nhất, không quá +1 mỗi giá trị, chia thành nhiều giá trị trong trường hợp phần còn lại> 1 hoặc hòa cho giá trị cao nhất).

ví dụ

   f 1 0 2
33 0 67

   f 1000 1000
50 50

   f 1 1 2 4
12 12 25 51

   f 0 0 0 5 0
0 0 0 100 0

   f 16 16 16 16 16 16
17 17 17 17 16 16

   f 0 100 5 0 7 1
0 89 4 0 7 0

Giải trình

  • f=.3 : 0 - 'f' là một biến, là loại động từ (3), được xác định bên dưới (: 0):
  • p=. biến 'p', được xây dựng từ:
    • y là một danh sách các số 1 0 2
    • +/y là '+' đặt giữa mỗi giá trị '/', tổng của danh sách 3
    • y % (+/y) là giá trị y gốc chia cho tổng: 0.333333 0 0.666667
    • 100 * (y%+/y)là 100 lần các giá trị đó: 33.33.. 0 0.66...để có được tỷ lệ phần trăm.
    • <. (100*y%+/y) là toán tử sàn được áp dụng cho tỷ lệ phần trăm: 33 0 66
  • r=. biến 'r', được xây dựng từ:
    • +/p là tổng của tỷ lệ phần trăm thả nổi: 99
    • 100 - (+/p) là 100 - tổng, hoặc các điểm phần trăm còn lại cần thiết để làm cho tỷ lệ phần trăm tổng thành 100.
  • kết quả, không được lưu trữ:
    • r $ 1 là danh sách 1s, miễn là số lượng vật phẩm chúng ta cần tăng: 1 [1 1 ..]
    • #p là độ dài của danh sách tỷ lệ phần trăm
    • (#p - r) là số lượng vật phẩm sẽ không được tăng lên
    • (#p-r) $ 0 là danh sách 0s miễn là tính: 0 0 [0 ..]
    • ((r$1) , (#p-r)$0) là danh sách 1s theo sau là danh sách 0s: 1 0 0
    • \: plà một danh sách các chỉ mục cần thực hiện pđể đặt nó theo thứ tự giảm dần.
    • /: (\:p)là một danh sách các chỉ mục cần thực hiện \:pđể sắp xếp theo thứ tự tăng dần
    • ((r$1),(#p-r)$0)/:\:pđang lấy các phần tử từ 1 1 .. 0 0 .. danh sách mặt nạ và sắp xếp để có 1s ở vị trí của tỷ lệ phần trăm lớn nhất, một cho mỗi số chúng ta cần tăng và 0 cho các số khác : 0 0 1.
    • p + ((r$1),(#p-r)$0)/:\:p là tỷ lệ phần trăm + mặt nạ, để tạo danh sách kết quả tính tổng 100%, là giá trị trả về của hàm.

ví dụ

33 0 66 sums to 99
100 - 99 = 1
1x1 , (3-1)x0 = 1, 0 0
sorted mask   = 0 0 1

33 0 66
 0 0  1
-------
33 0 67

  • ) kết thúc định nghĩa.

Tôi không có nhiều kinh nghiệm với J; Tôi sẽ không quá ngạc nhiên nếu có một "danh sách biến thành tỷ lệ phần trăm của toàn bộ" hoạt động được xây dựng và một cách sạch hơn để "tăng n giá trị lớn nhất". (Đây là ít hơn 11 byte so với lần thử đầu tiên của tôi).


1
Rất tuyệt. Tôi có một giải pháp python nhưng nó dài hơn cái này rất nhiều. Công việc tốt đẹp!
DaveAlger

1
Nếu bạn không nhận thấy, các quy tắc đã thay đổi, vì vậy bạn sẽ có thể rút ngắn đáng kể điều này.
lirtosiast

@DaveAlger cảm ơn! @ThomasKwa Tôi nhận thấy, tôi không chắc nó giúp tôi đáng kể - lần đầu tiên tôi có thể nhận được -2 ký tự. Tôi sẽ cần thay đổi list[0:100-n] + list[:-100-n]cách tiếp cận - và tôi chưa nghĩ ra cách nào khác để tiếp cận nó.
TessellatingHeckler

4

JavaScript (ES6), 81 byte

a=>(e=0,a.map(c=>((e+=(f=c/a.reduce((c,d)=>c+d)*100)%1),f+(e>.999?(e--,1):0)|0)))

Điều kiện "phải bằng 100" (thay vì làm tròn và cộng) gần gấp đôi mã của tôi (từ 44 lên 81). Bí quyết là thêm một bình cho các giá trị thập phân, khi nó đạt 1, lấy 1 từ chính nó và thêm nó vào số hiện tại. Vấn đề sau đó là các điểm nổi, có nghĩa là một cái gì đó như [1,1,1] còn lại là 0,9999999999999858. Vì vậy, tôi đã thay đổi séc thành lớn hơn 0,999 và quyết định gọi nó đủ chính xác.


4

Haskell, 42 27 byte

p a=[div(100*x)$sum a|x<-a]

Khá nhiều phương pháp tầm thường trong Haskell, với một vài khoảng trống được loại bỏ để chơi gôn.

Bảng điều khiển (dấu ngoặc bao gồm phù hợp với ví dụ):

*Main> p([1,0,2])
[33,0,66]
*Main> p([1000,1000])
[50,50]
*Main> p([1,1,2,4])
[12,12,25,50]
*Main> p([0,0,0,5,0])
[0,0,0,100,0]

Chỉnh sửa: thực hành đặt của tôi, thực hiện một số thay thế rõ ràng.

Nguyên:

p xs=[div(x*100)tot|x<-xs]where tot=sum xs

1
Tổng của danh sách nên là 100. Trong ví dụ đầu tiên của bạn, nó là 99
Damien

4

Thạch , 7 byte

-2 cảm ơn Dennis, nhắc nhở tôi sử dụng một tính năng mới khác ( Ä) và sử dụng :thay vì những gì tôi đã có ban đầu.

ŻÄ׳:SI

Hãy thử trực tuyến!

Thạch , 11 byte

0;+\÷S×ȷ2ḞI

Hãy thử trực tuyến!

Thực hiện cùng với caird coinheringaahinguser202729 trong trò chuyện .

Làm thế nào nó hoạt động

0; + \ S × 2ḞI - Chương trình đầy đủ.

0; - Chuẩn bị 0.
  + \ - Tổng tích lũy.
    S - Chia cho tổng của đầu vào.
      × 2 - Lần 100. Được thay thế bởi × trong phiên bản liên kết đơn âm.
         ḞI - Tầng mỗi, tính toán số gia (deltas, sự khác biệt).

3

Haskell, 63 56 55 byte

p l=tail>>=zipWith(-)$[100*x`div`sum l|x<-0:scanl1(+)l]

3

Perl, 42 byte

Dựa trên thuật toán của Dennis

Bao gồm +1 cho -p

Chạy với danh sách các số trên STDIN, ví dụ:

perl -p percent.pl <<< "1 0 2"

percent.pl:

s%\d+%-$-+($-=$a+=$&*100/eval y/ /+/r)%eg


2

Python 2, 89 byte

def f(L):
 p=[int(x/0.01/sum(L))for x in L]
 for i in range(100-sum(p)):p[i]+=1
 return p

print f([16,16,16,16,16,16])
print f([1,0,2])

->

[17, 17, 17, 17, 16, 16]
[34, 0, 66]

2

Brain-Flak , 150 byte

((([]){[{}]({}<>)<>([])}{})[()])<>([]){{}<>([{}()]({}<([()])>)<>(((((({})({})({})){}){}){}{}){}){}(<()>))<>{(({}<({}())>)){({}[()])<>}{}}{}([])}<>{}{}

Hãy thử trực tuyến!

Bắt đầu từ cuối và làm việc ngược, mã này đảm bảo ở mỗi bước rằng tổng của các số đầu ra cho đến nay bằng tổng tỷ lệ phần trăm gặp phải, làm tròn xuống.

(

  # Compute and push sum of numbers
  (([]){[{}]({}<>)<>([])}{})

# And push sum-1 above it (simulating a zero result from the mod function)
[()])

<>

# While elements remain
([]){{}

  # Finish computation of modulo from previous step
  <>([{}()]({}

    # Push -1 below sum (initial value of quotient in divmod)
    <([()])>

  # Add to 100*current number, and push zero below it
  )<>(((((({})({})({})){}){}){}{}){}){}(<()>))

  # Compute divmod
  <>{(({}<({}())>)){({}[()])<>}{}}{}

([])}

# Move to result stack and remove values left over from mod
<>{}{}

2

JavaScript (ES6) 60 63 95

Thích nghi và đơn giản hóa từ câu trả lời (sai) của tôi cho một thách thức khác
Thk đến @ l4m2 vì phát hiện ra rằng điều này cũng sai

Đã sửa lỗi tiết kiệm 1 byte (và ít hơn 2 byte, không tính tên F=)

v=>v.map(x=>(x=r+x*100,r=x%f,x/f|0),f=eval(v.join`+`),r=f/2)

Kiểm tra chạy đoạn mã dưới đây trong bất kỳ trình duyệt tuân thủ EcmaScript 6 nào

F=
v=>v.map(x=>(x=r+x*100,r=x%f,x/f|0),f=eval(v.join`+`),r=f/2)

console.log('[1,0,2] (exp [33,0,67] [34,0,66])-> '+F([1,0,2]))
console.log('[1000,1000] (exp [50,50])-> '+F([1000,1000]))
console.log('[1,1,2,4] (exp[12,12,25,51] [13,12,25,50] [12,13,25,50] [12,12,26,50])-> '+F([1,1,2,4]))
console.log('[0,0,0,5,0] (exp [0,0,0,100,0])-> '+F([0,0,0,5,0]))
console.log('[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,980] -> '+F([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,980]))
console.log('[2,2,2,2,2,3] -> ' + F([2,2,2,2,2,3]))
<pre id=O></pre>


Thất bại vào[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,980]
l4m2

@ l4m2 thất bại vì sao? Tổng là 100 vàany single resulting integer returned as a percentage is off by no more than 1 in either direction.
edc65

Người cuối cùng nên có nhiều nhất là 98, nhưng đó là 100
l4m2

@ l4m2 uh, đúng rồi, cảm ơn. Hãy nghĩ lại
edc65

@ l4m2 nên được sửa ngay bây giờ
edc65

1

Rust, 85 byte

Điều này sử dụng các vectơ thay vì mảng vì theo như tôi biết thì không có cách nào để chấp nhận các mảng có nhiều độ dài khác nhau.

let a=|c:Vec<_>|c.iter().map(|m|m*100/c.iter().fold(0,|a,x|a+x)).collect::<Vec<_>>();

1

JavaScript, 48 byte

F=

x=>x.map(t=>s+=t,y=s=0).map(t=>-y+(y=100*t/s|0))

// Test 
console.log=x=>O.innerHTML+=x+'\n';


console.log('[1,0,2] (exp [33,0,67] [34,0,66])-> '+F([1,0,2]))
console.log('[1000,1000] (exp [50,50])-> '+F([1000,1000]))
console.log('[1,1,2,4] (exp[12,12,25,51] [13,12,25,50] [12,13,25,50] [12,12,26,50])-> '+F([1,1,2,4]))
console.log('[0,0,0,5,0] (exp [0,0,0,100,0])-> '+F([0,0,0,5,0]))
<pre id=O></pre>


0

Jq 1.5 , 46 byte

add as$s|.[1:]|map(100*./$s|floor)|[100-add]+.

Mở rộng

  add as $s               # compute sum of array elements
| .[1:]                   # \ compute percentage for all elements 
| map(100*./$s|floor)     # / after the first element
| [100-add] + .           # compute first element as remaining percentage

Hãy thử trực tuyến!


0

PHP, 82 byte

for(;++$i<$argc-1;$s+=$x)echo$x=$argv[$i]/array_sum($argv)*100+.5|0,_;echo 100-$s;

lấy đầu vào từ các đối số dòng lệnh, in tỷ lệ phần trăm được phân tách bằng dấu gạch dưới.

Chạy với -nrhoặc thử trực tuyến .


Kết quả này xuất ra 15_15_15_15_15_25khi được cung cấp đầu vào [2,2,2,2,3], điều này không đúng bởi vì3/13 ~= 23.1%
Sophia Lechner

@SophiaLechner Câu trả lời nào đúng?
Tít

Hầu hết làm, thực sự. Các câu trả lời đúng cho đến nay dường như được xây dựng xung quanh một trong hai thuật toán; các vòng đầu tiên giảm tỷ lệ phần trăm của các khoản tiền tích lũy và có sự khác biệt; thứ hai tính toán các tầng của tỷ lệ phần trăm và sau đó tăng đủ tỷ lệ phần trăm khác biệt để đưa tổng số lên 100.
Sophia Lechner

@SophiaLechner Tôi không có nghĩa là tôi sẽ nhìn vào nó; nhưng tôi sẽ làm sau. Cảm ơn đã chú ý.
Tít
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.