Rafting Sorunu (Sırt çantası varyantı)


20

Benden ilk bulmaca, iyileştirme önerileri memnuniyetle aldı!

Senaryo; Bir beyaz su rafting şirketi için yönetici olarak çalışıyorsunuz. Her sabah, bir rezervasyon listesi verilir ve bunları sal yüklere ayırmanız gerekir. Seçtiğiniz dilde bunu sizin için yapan bir program veya işlev yazın.

Her sal en fazla nmüşteriye sahiptir ve her rezervasyon 1 ile nkişi (dahil) arasındaki bir grup içindir . Aşağıdaki kurallara uyulmalıdır;

  • Hiçbir grup bölünemez. Birlikte rezervasyon yaptılarsa, hepsinin aynı salda olması gerekir.

  • Salların sayısı en aza indirilmelidir.

  • Yukarıdaki iki kurala bağlı olarak, gruplar sallar arasında olabildiğince eşit şekilde yayılmalıdır.

Girdiler. Sayı n(bunun pozitif bir tamsayı olduğunu varsayabilirsiniz) ve tüm rezervasyonların boyutu. Diliniz bu tür şeyleri destekliyorsa, bu bir dizi, liste veya benzer bir veri yapısı olabilir. Tüm bunlar 1 ile arasında pozitif tamsayılar olacaktır n. Rezervasyonların sırası tanımlanmamıştır ve önemli değildir.

Çıktı. Sal yükleri olarak gruplandırılmış rezervasyon numaralarının listesi. Gruplama açık bir şekilde belirtilmelidir, örneğin;

  • bir liste veya dizi dizisi.
  • her bir sal için virgülle ayrılmış bir liste. Her sal arasında yeni satır.

Üçüncü kuralı nasıl uygulayacağınız size bağlıdır, ancak bu, ortalama sal doluluğunu bulmayı ve mümkün olduğunca sapmaları en aza indirmeyi içerebilir. İşte bazı test örnekleri.

n  Bookings       Output
6  [2,5]          [5],[2]
4  [1,1,1,1,1]    [1,1,1],[1,1]
6  [2,3,2]        [2,2],[3]
6  [2,3,2,3]      [2,3],[2,3]
6  [2,3,2,3,2]    [2,2,2],[3,3]
12 [10,8,6,4,2]   [10],[8,2],[6,4]
6  [4,4,4]        [4],[4],[4]
12 [12,7,6,6]     [12],[7],[6,6]

Standart kurallar geçerlidir, en kısa kod kazanır. İyi eğlenceler!

Düzenlenen; Üçüncü kural için mümkün olduğu kadar eşit tanımlamanın önerilen bir yolu .

Sal sayısı rbelirlendikten sonra (ikinci kurala tabi olarak), ortalama doluluk a, rezervasyonlar toplanarak ve bölünerek hesaplanabilir r. Her bir sal, ortalama doluluk sapma kullanılarak bulunabilir d(x) = abs(n(x)-a)burada, n(x)her bir sal insanlar ve sayısıdır 1 <= x <= r. f(y)Kesinlikle pozitif olan ve tüm pozitif için kesinlikle pozitif bir ilk ve negatif olmayan ikinci türeve sahip bazı sürekli, tek değerli fonksiyonlar için , negatif yolmayan bir miktarı F, toplamının toplamı olarak tanımlarız f(d(x)), 1 <= x <= r. İlk iki kuralı Fkarşılayan ve küresel minimum değere eşit olan herhangi bir sal tahsisi seçeneği de üçüncü kuralı karşılayacaktır.


3
İleride başvurmak için, göndermeden önce bir sorun hakkında geri bildirim almak için korumalı alanımıza gönderebilirsiniz.
Buğday Büyücüsü

Programlama Bulmacaları ve Kod Golf hoş geldiniz! Bu ilk meydan okuma olduğunu bilmek güzel bir meydan okuma gibi görünüyor. Ancak bir dahaki sefere, meydan okumayı önce Sandbox'ta yayınlamak daha iyi olabilir , böylece insanlar orada önerilerde bulunabilir. Daha sonra zorluğun bittiğini düşündüğünüzde, ana sitede yayınlayabilirsiniz. Okuduğunuz için teşekkürler ve iyi günler!
Matthew Roh

Mümkün olduğunca eşit olarak nasıl ölçülür?
Dennis

@Dennis; Bunu bir düzenlemede tanımlamak için önerilen bir yol koyacağım. Ancak farklı bir yönteminiz varsa ve cevabınız için bunu haklı çıkarabiliyorsanız, sorun değil.
Gwyn

1
Neyin geçerli ve neyin geçerli olmadığı açık olduğu sürece, işleri uygulamaya kadar bırakmak iyidir ve son düzenlemeniz bu imo'yu başarır. Yine de g(y) = y(ikinci türev sıfır) veya g(y) = y²(ilk ne zaman sıfır derviate sıfır ) kullanamayacağımızdan biraz şaşırdım y = 0.
Dennis

Yanıtlar:


2

Perl 6 , 163158 bayt

{[grep $^n>=*.all.sum,map ->\p{|map {p[0,|$_ Z..^|$_,p]},(1..^p).combinations},$^s.permutations].&{.grep: .map(+*).min}.min({.map((*.sum-$s.sum/$_)**2).sum})}

Çevrimiçi deneyin!

Nasıl çalışır

  • map ->\p{|map {p[0,|$_ Z..^|$_,p]},(1..^p).combinations},$^s.permutations

    Girdi dizisinin tüm permütasyonlarının tüm olası bölümlerini oluşturur.

  • grep $^n>=*.all.sum,

    Sal kullanılmayanları filtreler.

  • .&{.grep: .map(+*).min}

    Sal sayısının minimum olduğu filtreleri filtreler.

  • .min({.map((*.sum-$s.sum/$_)**2).sum})}

    İlkini en az ∑ (n x -a) 2 ile alır .

@ Pietu1998 sayesinde -4 bayt


Sonucu .abskare yaparsanız yapmanız gerekir mi?
PurkkaKoodari

@ Pietu1998: Yapmıyorum, iyi yakaladım.
smls

3

Haskell 226 228 234 268 bayt

Haskell'de naif cevap

import Data.List
o=map
u=sum
p=foldr(\x t->o([x]:)t++[(x:y):r|(y:r)<-t>>=permutations])[[]]
m x=foldl(\[m,n]x->[m+(x-m)/(n+1),n+1])[0,0]x!!0
a!z=abs$u z-a
s t=(length t,u$o((m$o u t)!)t)
a n=head.sortOn s.filter(all$(<=n).u).p

Veya dinsiz

partition' :: [a] -> [[[a]]]
partition' [] = [[]]
partition' (x:xs) = [[x]:ps     | ps <- partition' xs]
                 ++ [(x:p):rest | ps <- partition' xs, (p:rest) <- permutations ps]

-- from Data.Statistics
mean :: [Double] -> Double
mean xs = fst $ foldl (\(m, n) x -> (m+(x-m)/n+1, n+1)) (0, 0) xs

diff :: Double -> [Double] -> Double
diff avg xs = abs $ sum xs - avg

rawScore :: [[Double]] -> Double
rawScore xs = sum . map (diff avg) $ xs where avg = mean . map sum $ xs

score :: [[Double]] -> (Int, Double)
score xs = (length xs, rawScore xs)

-- from Data.Ord
comparing :: (Ord b) => (a -> b) -> a -> a -> Ordering
comparing p x y = compare (p x) (p y)

candidates :: Double -> [Double] -> [[[Double]]]
candidates n xs = filter (all (\ ys -> sum ys <= n)) . partition' $ xs

answer :: Double -> [Double] -> [[Double]]
answer n xs = minimumBy (comparing score) $ candidates n xs

Bazı test senaryolarında

import Text.PrettyPrint.Boxes

testCases :: [(Double, [Double])]
testCases = [(6 , [2,5])
            ,(4 , [1,1,1,1,1])
            ,(6 , [2,3,2])
            ,(6 , [2,3,2,3])
            ,(6 , [2,3,2,3,2])
            ,(12, [10,8,6,4,2])
            ,(6 , [4,4,4])
            ,(12, [12,7,6,6])]

runTests tests = transpose 
                 $ ["n", "Bookings", "Output"]
                 : map (\(n, t) -> [ show . floor $ n
                                   , show . map floor $ t
                                   , show . map (map floor) $ a n t]) tests

test = printBox 
     . hsep 3 left . map (vcat top) . map (map text) . runTests $ testCases

nerede testverimleri

n    Bookings       Output
6    [2,5]          [[2],[5]]
4    [1,1,1,1]      [[1,1],[1,1,1]]
6    [2,3,2]        [[2,2],[3]]
6    [2,3,2,3]      [[2,3],[2,3]]
6    [2,3,2,3,2]    [[2,2,2],[3,3]]
12   [10,8,6,4,2]   [[10],[8,2],[6,4]]
6    [4,4,4]        [[4],[4],[4]]
12   [12,7,6,6]     [[12],[7],[6,6]]

Düzenle

@Flawr ve @ nimi için teşekkürler.

pBiraz ezilmiş .

Birkaç bayt tıraş oldu.


1
Sen ayarlayabilirsiniz s=sumve daha sonra kullanmak syerine sum, ve belki de yerini alabilir fst$ ...ile ...!!0.
flawr

1
Sen yerini alabilir minimumBy(c s)ile head.sortOn sve işlevini kaldırmak c. Ayrıca: \t->sum t<=nis (<=n).sum.
nimi

@flawr, iyi bir öneri, teşekkürler!
walpen

0

Python3, 224 bayt

def p(c):
 if len(c)==1:yield[c];return
 for s in p(c[1:]):
  for n,u in enumerate(s):yield s[:n]+[[c[0]]+u]+s[n+1:]
  yield[[c[0]]]+s
s=sum
r=lambda n,b:min(p(b),key=lambda c:s(abs(s(x)-s(b)/(s(b)//n+1))for x in c))

Testcases ile:

tc = [[6,[2,5]],[4,[1,1,1,1,1]],[6,[2,3,2]],[6,[2,3,2,3]],[6,[2,3,2,3,2]],[12,[10,8,6,4,2]],[6,[4,4,4]],[12,[12,7,6,6]]]
for case in tc:
    print(str(case[0]).ljust(3),str(case[1]).ljust(16),"|",r(*case))

O nasıl çalışır?

pFonksiyon sadece belirli bir listesinin tüm bölümleri (tüm olası yolları alt listelere o kadar bölmek için) üretir. s=sumsadece sum fonksiyonunu yeniden adlandırır, böylece son satır tüm işi yapar.

r=lambda n,b:min(p(b),key=lambda c:s(abs(s(x)-s(b)/(s(b)//n+1))for x in c))
r=lambda n,b:                                                               Initialize the lambda
                 p(b)                                                       Calculate all possible raft arrangements
                     ,key=lambda c:                                         Map the following lambda onto the list:
                                              s(b)/(s(b)//n+1)              Calculate the ideal average amount of people per raft
                                     abs(s(x)-                )             Calculate how close is the current raft
                                                               for x in c   For each raft in the partition
                                   s(                                    )  Sum it (the sum is a score of how close to ideal the function is),
             min(                                                         ) And find the lowest valued partition.

Bunun daha fazla golf oynayabileceğinden eminim, özellikle pfonksiyon, ama ben zaten saatlerce çalıştım, işte burada.

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.