整数パーセント


21

正の整数のリストを受け取り、同じ位置にある対応する整数の合計のパーセントに近い整数のリストを返す関数を作成します。

返されるリスト内のすべての整数は、正確に100まで加算する必要があります。渡された整数の合計は0より大きいと仮定できます。どちらの方向でも1を超えてオフになりません。

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]

これはなので、バイト単位の最短コードが勝ちです!


アルゴリズムは決定的でなければなりませんか?制限時間内に常に終了する必要がありますか?
リトシアスト

すでに似たようなより一般的な丸めの問題がありました
-edc65

1
別のテストケースを追加することをお勧めしますp([2,2,2,2,2,3])。それには多くの有効な答えがありますが、すべて2のを同じ値にマッピングできるわけではありません。これにより、丸めがそれほど悪くないため、以前のすべてのテストケースで機能する非常に単純なアルゴリズムが多くなくなります。
ソフィア・レヒナー

4
できますp([1000,1000]) -> [49,51]か?
l4m2

1
@ l4m2それは間違っているようだが、それはスペックは以下のような結果の両方が、1、それ以上ではオフになっています
edc65

回答:


20

Dyalog APL、21 19 16バイト

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

上記は、列車に相当するものです

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

オンラインでお試しください。

使い方

                 ⍝ 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
フェルマーだけがあなたからゴルフのレッスンを受けられたなら。
TessellatingHeckler

1
@TessellatingHecklerあなたがそこで何をしたかわかります。たぶん、彼は証拠のために余白に十分な余地を持っているでしょう。:)
mbomb007

14

TI-BASIC、26 23 16バイト

TI-83 + / 84 +シリーズの計算機用。

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

美しいアルゴリズムを作成してくれた@Dennisに感謝します!パーセントに変換した後、リストの累積合計を取得し、次にフロア、0を前に付け、差を取得します。ᴇ2は、よりも1バイト短くなってい100ます。

同じバイト数は次のとおりです。

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

楽しい事実は:%ある2バイトのトークンによってその乗算数0.01-が、電卓にそれをタイプする方法はありません!外部でソースを編集するか、アセンブリプログラムを使用する必要があります。

古いコード:

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

最初の行はすべてのフロアパーセントを計算し、2行目は最初のN要素に1を加算Nします。ここで、残りのパーセンテージです。cumSum(「累積合計」の略です。

{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}

N>dim([list]フローリングでパーセンテージが1を超えて減少することはないため、がありません。


必ずどのようにあなたはここでバイト、それは私にはとても長い23以上に見えるカウントされません
デビッドArenburg

@DavidArenburgこれは人間が読める形式です。すべてのトークン(int(sum(Ans、など)は1バイトのみを占有します。
デニス

4
+1これは、このサイトで見た中で最も印象的なTI-BASICゴルフの1つです。
PhiNotPi

トーマス、この答えは素晴らしい!
-DaveAlger

%シンボルを入力する方法はありませんか?私はそれがシンボルカタログで見つけられると思っていたでしょう...また、私はTI-84 +シルバーを手に入れるべきです。しばらく使用していません。ブロックデュードは素晴らしいです。
mbomb007

7

CJam、25 23 22バイト

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

25→24の@ Sp3000に感謝します。

オンラインでお試しください。

使い方

_                   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

Mathematica、41バイト

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

待って、ここで何が起こるの?
seequ

@Seeqこのアルゴリズムは、TI-BASIC回答の古いコードに似ています。すべてのフロアパーセントを計算し、最初のN要素に1を追加Nします。ここで、残りのパーセンテージです。
-alephalpha

5

J(8.04ベータ)、59バイト(30盗難バイト)

デニスのAPL回答の 30バイトのリテラルJポート:

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

    f 1 1 2 4
12 13 25 50

59バイトの答え、私が自分でできること:

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

(残りが1を超えない場合、または最大値が同点の場合、それぞれ+1以下の最高値に移動する必要があることに基づいて、複数の値に分割します)。

例えば

   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

説明

  • f=.3 : 0 -「f」は変数であり、動詞タイプ(3)であり、以下で定義されています(:0):
  • p=. 以下から作成された変数「p」:
    • y 数字のリストです 1 0 2
    • +/y 各値「/」の間に「+」、リストの合計 3
    • y % (+/y) 元のy値を合計で割ったものです。 0.333333 0 0.666667
    • 100 * (y%+/y)これらの値の100倍です:33.33.. 0 0.66...パーセンテージを取得します。
    • <. (100*y%+/y) パーセンテージに適用されるフロア演算子です。 33 0 66
  • r=. 以下から作成された変数 'r':
    • +/p は、フロアパーセンテージの合計です: 99
    • 100 - (+/p) 100-合計、またはパーセンテージの合計を100にするために必要な残りのパーセンテージポイントです。
  • 結果、保存されません:
    • r $ 1 アイテムの数を増やす必要がある限り、1のリストです。 1 [1 1 ..]
    • #p 割合リストの長さ
    • (#p - r) インクリメントされないアイテムの数です
    • (#p-r) $ 0 カウントする限り、0のリストです。 0 0 [0 ..]
    • ((r$1) , (#p-r)$0) 1のリストの後に0のリストが続きます。 1 0 0
    • \: pp降順で取得するために取得するインデックスのリストです。
    • /: (\:p)\:p昇順で置くために取得するインデックスのリストです
    • ((r$1),(#p-r)$0)/:\:pは、1 1 .. 0 0 ..マスクリストから要素を取得し、最大パーセンテージの位置に1が存在するようにソートします。増分する必要がある各数値に1つずつ、他の数値には0です0 0 1
    • p + ((r$1),(#p-r)$0)/:\:p は百分率+マスクで、合計が100%になる結果リストを作成します。これは関数の戻り値です。

例えば

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

そして

  • ) 定義の終わり。

私はJをあまり経験していません。「リストを合計のパーセンテージに変換する」操作と、「n個の最大値をインクリメントする」クリーンな方法が組み込まれていても、それほど驚くことではありません。(これは最初の試行より11バイト少ないです)。


1
とてもかっこいい。私はPythonソリューションを持っていますが、これよりはるかに長いです。よくやった!
DaveAlger

1
気づいていない場合は、ルールが変更されているため、これを大幅に短縮できるはずです。
リトシアスト

@DaveAlgerありがとう!@ThomasKwa私は気づいた、それが私にかなり役立つかどうかわからない-私は-2文字を得ることができる最初の試み。list[0:100-n] + list[:-100-n]アプローチを変更する必要があります-そして、アプローチする別の方法を考えていませんでした。
TessellatingHeckler

4

JavaScript(ES6)、81バイト

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

この「100に等しくなければならない」条件(切り上げと加算ではなく)により、コードがほぼ2倍になりました(44から81)。トリックは、1に達すると1から1を取り、それを現在の数に追加する10進値のポットを追加することでした。問題は浮動小数点でした。つまり、[1,1,1]のようなものは.9999999999999858の残りを残します。そこで、チェックを.999より大きい値に変更し、その精度を十分に高くすることにしました。


4

Haskell、42 27バイト

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

Haskellの取るに足らない方法で、ゴルフのためにいくつかのスペースが削除されています。

コンソール(例と一致するように括弧が含まれています):

*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]

編集:私のパッティングを練習し、いくつかの明らかな交換を行いました。

元の:

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

1
リストの合計は100になります。最初の例では、99-
ダミアン

4

ゼリー、7バイト

-2 Dennisに感謝します。別の新機能(Ä)を使用することを思い出させ、:最初に持っていたものの代わりに使用します。

ŻÄ׳:SI

オンラインでお試しください!

ゼリー、11バイト

0;+\÷S×ȷ2ḞI

オンラインでお試しください!

チャットでのcoairheringaahinguser202729一緒行います。

使い方

0; + \÷S×ȷ2ḞI-完全なプログラム。

0; -0を付加します。
  + \-累積合計。
    ÷S-入力の合計で除算されます。
      ×ȷ2-Times100。モナドリンクバージョンでは׳に置き換えられました。
         ḞI-各フロア、増分(デルタ、差分)を計算します。


3

Perl、42バイト

デニスのアルゴリズムに基づく

+1を含む -p

STDIN上の数字のリストで実行します。例えば

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

percent.pl

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


2

Python 2、89バイト

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バイト

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

オンラインでお試しください!

このコードは、最後から始めて逆方向に進み、各ステップで、これまでの出力数の合計が、発生した合計パーセンテージと等しくなるように切り捨てます。

(

  # 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

これも間違っていたことを発見したため、@ l4m2 への別のチャレンジThkへの私の(間違った)回答からの適応と簡略化

1バイトの保存を修正(および名前をカウントしない2バイト未満F=

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

EcmaScript 6準拠のブラウザーで以下のスニペットを実行してテストします

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>


失敗しました[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,980]
l4m2

@ l4m2はなぜ失敗しましたか?合計は100およびany single resulting integer returned as a percentage is off by no more than 1 in either direction.
-edc65

最後の1つは98までに最大1つオフにする必要がありますが、100
l4m2

@ l4m2ええ、そうです、ありがとう。もう一度考える時間
edc65

@ l4m2は今修正する必要があります
edc65

1

さび、85バイト

私が知る限り、複数の異なる長さの配列を受け入れる方法がないため、これは配列の代わりにベクトルを使用します。

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

1

JavaScript、48バイト

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バイト

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

拡大

  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

オンラインでお試しください!


0

PHP、82バイト

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

コマンドライン引数から入力を受け取り、アンダースコアで区切られたパーセンテージを出力します。

で実行する-nr、オンラインで試してください


この出力は15_15_15_15_15_25、入力与えられた[2,2,2,2,3]権利ではありませんので、3/13 ~= 23.1%
ソフィアレヒナー

@SophiaLechnerどの答えが正しいですか?
タイタス

ほとんどの場合、実際に。これまでのところ、正解は2つのアルゴリズムのいずれかを中心に構築されているようです。最初は累積合計のパーセンテージを四捨五入し、差を取る。第二の計算パーセントの床、次いで100に合計をもたらすために十分な別個のパーセンテージを増加
ソフィアレヒェナー

@SophiaLechner調べないという意味ではありませんでした。しかし、後でやります。気づいてくれてありがとう。
タイタス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.