Tam Sayı Yüzdesi


21

Pozitif tamsayılar listesine giren ve aynı konumda karşılık gelen tamsayı için toplam yüzdesine yaklaşan bir tamsayı listesi döndüren bir fonksiyon yazın.

Döndürme listesindeki tüm tam sayıların tam olarak 100'e kadar eklenmesi gerekir. Girilen tam sayıların toplamının 0'dan büyük olduğunu varsayabilirsiniz. her iki yönde de 1'den fazla kapalı değil.

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]

Bu , bayt cinsinden en kısa kod kazanır!


Algoritmamız belirleyici mi olmalı? Her zaman sınırlı bir süre içinde sona ermeli mi?
lirtosiast

Zaten benzer ama daha genel bir yuvarlama problemi
yaşadık

1
Sana başka bir test durumda eklemek öneririz: p([2,2,2,2,2,3]). Pek çok olası hukuki cevabı vardır, fakat hepsi 2aynı değere eşlenemez. Bu, önceki tüm test durumlarında çalışan aşırı basit algoritmaları elimine eder, çünkü yuvarlama çok kötü değildir.
Sophia Lechner

4
Olabilir p([1000,1000]) -> [49,51]mi?
18m2

1
spec aşağıdaki yüzden @ l4m2, artık Yanlış görünüyor, ancak her iki sonuç 1 ile kapalı ve
edc65

Yanıtlar:


20

Dyalog APL, 21 19 16 bayt

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

Yukarıdaki bir tren eşdeğerdir

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

Çevrimiçi deneyin.

Nasıl çalışır

                 ⍝ 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
Keşke Fermat senden golf dersi almış olsaydı.
TessellatingHeckler

1
@TessellatingHeckler Orada ne yaptığını gördüm. Belki o zaman delilleri için sınırda yeterince yer açardı. :)
mbomb007

14

TI-BASIC, 26 23 16 bayt

TI-83 + / 84 + serisi hesap makineleri için.

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

Güzel bir algoritma için @Dennis'e teşekkürler! Yüzdeleri dönüştürdükten sonra listenin kümülatif toplamını alırız, sonra zemine, önden 0 a basar ve farkları alırız. ᴇ2bir bayttan daha kısa 100.

Aynı byte sayısında:

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

Eğlenceli bir gerçek: %Bir olan iki baytlık belirteç ile bu çarpar bir sayı .01-ama hesap makinesi içine yazmak için bir yolu yoktur! Kaynağı dışarda düzenlemeniz veya bir montaj programı kullanmanız gerekir.

Eski kod:

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

İlk satır, tüm katlanmış yüzdeleri hesaplar, ardından ikinci satır, ilk Nelemana 1 ekler , burada Nkalan yüzde. cumSum("kümülatif toplam" anlamına gelir.

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

Yapmayacağız N>dim([list]çünkü döşeme oranlarında yüzde 1'den fazla bir azalma olmaz.


Buradaki baytları nasıl
saydığınızdan

@DavidArenburg Bu sadece insan tarafından okunabilen bir formdur. Tüm simgeler ( int(, sum(, Ansvs.) tek bayt işgal eder.
Dennis,

4
+1 Bu, bu sitede gördüğüm en etkileyici TI-BASIC golflerinden biri.
PhiNotPi

Thomas bu cevap çarpıcı!
DaveAlger

%Sembolü girmenin bir yolu olmadığından emin misin ? Sembol kataloğunda bulunabileceğini düşünürdüm ... Ayrıca, TI-84 + Silver'imi çıkarmalıyım. Bir süredir kullanmadım. Blok Dostum harika.
mbomb007

7

CJam, 25 23 22 bayt

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

25 → 24 için @ Sp3000'e teşekkürler.

Çevrimiçi deneyin.

Nasıl çalışır

_                   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 bayt

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

Bekle, burada ne olacak?
06'da

@Seeq Algoritma, TI-BASIC cevabındaki eski kod gibidir. Tüm katlanmış yüzdeleri hesaplar, sonra kalan yüzdelerin Nolduğu ilk elemana 1 ekler N.
alephalpha,

5

J (8.04 beta) , 59 bayt (çalınan 30 bayt)

Dennis'in APL cevabının 30 bayt değişmez J-portu :

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

    f 1 1 2 4
12 13 25 50

59 byte cevap, kendim yapabileceğimin en iyisi:

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

(Kalan değer> 1 veya en yüksek değer için bir bağ olması durumunda, her biri + 1'den fazla olmayan en yüksek değerlere gitmek zorunda kalırsa).

Örneğin

   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

açıklama

  • f=.3 : 0 - 'f', aşağıda tanımlanan bir fiil tipi (3) olan bir değişkendir (: 0):
  • p=. 'p' değişkeni, yerleşik:
    • y bir sayı listesidir 1 0 2
    • +/y '+', her değerin arasına koyulur '/', listenin toplamı 3
    • y % (+/y) Özgün y değerleri toplamına bölünür: 0.333333 0 0.666667
    • 100 * (y%+/y)bu değerlerin 100 katıdır: 33.33.. 0 0.66...Yüzdeleri elde etmek için.
    • <. (100*y%+/y) döşeme operatörü yüzdelere uygulanır: 33 0 66
  • r=. 'r' değişkeni, yerleşik:
    • +/p katlanmış yüzdelerin toplamı: 99
    • 100 - (+/p) 100'tür - yüzdeleri 100'e çıkarmak için gereken kalan puan.
  • sonuç, saklanmadı:
    • r $ 1 artırmak için gereken öğe sayısı kadar 1'lerin bir listesidir: 1 [1 1 ..]
    • #p yüzde listesinin uzunluğu
    • (#p - r) artırılmayacak öğelerin sayısıdır
    • (#p-r) $ 0 bu sayı olduğu sürece 0'ların listesidir: 0 0 [0 ..]
    • ((r$1) , (#p-r)$0) 1s listesi ve 0s listesi: 1 0 0
    • \: ppazalan sıraya koymak için alınacak dizinlerin listesidir .
    • /: (\:p)\:pbu artan düzende koymak için alınacak dizinlerin listesi
    • ((r$1),(#p-r)$0)/:\:p1 1 den elemanlar alarak .. 0 0 .. maske liste ve sıralama bu yüzden büyük yüzdeleri, biz artım gereken her numara için birinin pozisyonlarda 1s ve 0'lar diğer sayılar için vardır: 0 0 1.
    • p + ((r$1),(#p-r)$0)/:\:p fonksiyon yüzdesi olan% 100 değerine ulaşan sonuç listesini yapmak için yüzdelikler + maskedir.

Örneğin

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

ve

  • ) tanımın sonu.

J konusunda pek tecrübeli değilim; İnşa operasyonda bir "toplam yüzdeleri içine dönüş listesi" ve "artım bir temizleyici yol varsa ben de sürpriz olmaz n çok büyük değerler". (Bu benim ilk denememden daha az 11 bayt).


1
Çok havalı. Bir piton çözümüm var ama bundan çok daha uzun sürüyor. İyi iş!
DaveAlger

1
Eğer farketmediyseniz, kurallar değişti, bu yüzden bunu önemli ölçüde kısaltabilirsiniz.
lirtosiast

@DaveAlger teşekkürler! @ThomasKwa Fark ettim, bana çok yardımcı olacağından emin değilim - ilk girişim -2 karakter alabilirim. list[0:100-n] + list[:-100-n]Yaklaşımı değiştirmem gerekir - ve yaklaşmanın başka bir yolunu düşünmedim.
TessellatingHeckler

4

JavaScript (ES6), 81 bayt

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

Bu "100'e eşit olmalı" koşulu (yuvarlama ve toplama yerine) kodumu neredeyse iki katına çıkardı (44'ten 81'e). İşin püf noktası, 1'e ulaştığında, kendisinden 1 alan ve o anki sayıya ekleyen ondalık değerler için bir pot eklemekti. O zaman sorun, kayan noktalardı, bu da [1,1,1] gibi bir şeyin 0,9999999999999858 kalanını bıraktığı anlamına geliyordu. Bu yüzden çeki 999'dan daha büyük olacak şekilde değiştirdim ve yeterince kesin olarak adlandırmaya karar verdim.


4

Haskell, 42 27 bayt

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

Hemen hemen Haskell'deki en önemsiz yöntem, golf oynamak için birkaç boşluk bırakılmış olması.

Konsol (örnekle tutarlı olması için dahil edilen braketler):

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

Düzenleme: benim koyarak pratik yaptı, bazı belirgin değişiklikler yaptı.

Orijinal:

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

1
Listenin toplamı 100 olmalıdır. İlk örnekte, bu 99
Damien

4

Jöle , 7 bayt

-2 Dennis sayesinde bana başka bir yeni özellik ( Ä) kullanmamı ve :başlangıçta sahip olduğumun yerine kullanmamı hatırlattı .

ŻÄ׳:SI

Çevrimiçi deneyin!

Jöle , 11 bayt

0;+\÷S×ȷ2ḞI

Çevrimiçi deneyin!

Yanında Bitti Caird coinheringaahing ve user202729 içinde sohbet .

Nasıl çalışır

0; + \ ÷ S × ȷ2ḞI - Tam program.

0; - 0 a bağımlı.
  + \ - Birikimli toplam.
    S - Girişin toplamına bölünür.
      × ȷ2 - Kez 100. Monodik bağlantı versiyonunda × ³ ile değiştirildi.
         FloorI - Her birini katlayın, artışları (deltalar, farklılıklar) hesaplayın.

3

Haskell, 63 56 55 bayt

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

3

Perl, 42 bayt

Dennis'in algoritmasına dayanarak

İçin +1 içerir -p

STDIN'deki sayıların listesiyle çalıştırın, örn.

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

percent.pl:

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


2

Python 2, 89 bayt

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 bayt

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

Çevrimiçi deneyin!

En baştan başlayarak geriye doğru çalışan bu kod, her adımda çıktı sayılarının toplamının, karşılaşılan toplam yuvarlağa eşit olmasını sağlar.

(

  # 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

(Yanlış) cevabımdan başka bir zorluğa uyarlanmış ve basitleştirilmiş
olduğunu keşfetmek cevabımdan Thk den @ l4m2 ye

1 bayt (ve 2 bayt daha az, adı saymadan) tasarruf düzeltildi F= )

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

Aşağıdaki snippet'i çalışan herhangi bir EcmaScript 6 uyumlu tarayıcıda test edin

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>


Başarısız oldu[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,980]
l4m2

@ l4m2 neden başarısız oldu? Toplam 100 veany single resulting integer returned as a percentage is off by no more than 1 in either direction.
edc65

Sonuncusu 98 ile en çok bir kapalı olmalıdır, ancak saat 100
l4m2'de 19-18

@ l4m2, doğru, teşekkürler. Tekrar düşünmek için zaman
edc65

@ l4m2 şimdi düzeltilmelidir
edc65

1

Pas, 85 bayt

Bu, diziler yerine vektörleri kullanır, çünkü bildiğim kadarıyla birden fazla farklı uzunluktaki dizileri kabul etmenin bir yolu yoktur.

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

1

JavaScript, 48 bayt

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 bayt

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

Expanded

  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

Çevrimiçi deneyin!


0

PHP, 82 bayt

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

komut satırı argümanlarından girdi alır, alt çizgi ile sınırlandırılmış yüzdeleri yazdırır.

Çevrimiçi olarak çalıştırın -nrveya deneyin .


Bunun çıktısı 15_15_15_15_15_25girdi verildiğinde [2,2,2,2,3]doğru çünkü değil,3/13 ~= 23.1%
Sophia Lechner

@SophiaLechner Cevaplardan hangisi bu doğru?
Titus

Aslında çoğu. Şimdiye kadar doğru cevaplar, iki algoritmadan birinin çevresinde oluşturulmuş gibi görünüyor; ilk kümülatif toplamların yüzdelerini yuvarlar ve farkı alır; ikincisi, yüzdelerin tabanlarını hesaplar ve sonra toplamı 100'e çıkarmak için yeterli yüzdeleri artırır.
Sophia Lechner

@SophiaLechner Bunu aramayacağım anlamına gelmiyordu; ama sonra yaparım. Fark ettiğin için teşekkürler.
Titus
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.