Unutmamalıyız ki, görevin özü aslında oldukça basittir; Haskell ile ilgili bir öğreticide belirtildiği gibi (bu göreve yönelik çözümün çalışılmasıyla yazılır, aşamalı olarak rafine edilir)
Şimdi bir an için programımızın nasıl çalışacağını düşünelim ve programı sahte kodda ifade edelim:
main = Read list of directories and their sizes.
Decide how to fit them on CD-Rs.
Print solution.
Kulağa makul geliyor mu? Ben de öyle düşünmüştüm.
Hayatımızı biraz basitleştirelim ve şimdilik programımızın dışında bir yerde (örneğin, " du -sb *
" ile) dizin boyutlarını hesaplayacağımızı ve bu bilgileri stdin'den okuyacağımızı varsayalım .
( Otostopçu rehberinden Haskell, Bölüm 1 )
(Ayrıca, sorunuzda, ortaya çıkan disk düzenlerini değiştirebilir (düzenleyebilir) ve ardından bunları yazmak için bir araç kullanabilirsiniz.)
Dosya koleksiyonunuzu bölmek için o Haskell öğreticisinden programın basit bir varyantını yeniden kullanabilir (uyarlayabilir ve yeniden kullanabilirsiniz).
Ne yazık ki, içinde başka bir cevap burada bahsettiğimiz bu aracı , esansiyel bölme görevi basitliği kullanıcı arayüzünün karmaşıklığı ve kabarmışlığın eşleşmeyen birkaç görevleri birleştirmek için yazılmıştır çünkü (; aşamada gerçekleştirilir rağmen, ama yine de düşünebildiğim en temiz şekilde bir arada değil).distribute
distribute
Kodundan biraz yararlanmanıza yardımcı olmak için, bir dosya koleksiyonunu bölmenin bu "temel" görevini gerçekleştirmeye yarayan distribute
( satır 380'de ) bash kodundan bir alıntı :
# Splitting:
function splitMirrorDir() {
if [[ ! -d "$THIS_BASES_DIR/$BASE/$type" ]]; then
echo $"No base fixed for $type" >&2
exit 1
fi
# Getting the list of all suitable files:
local -a allFiles
let 'no = 0' ||:
allFiles=()
# no points to the next free position in allFiles
# allFiles contains the constructed list
for p in "$THIS_BASES_DIR/$BASE/$type"/*.rpm; do
if [[ ! -e "$p" ]]; then
# fail on non-existent files
echo $"Package file doesn't exist: " "$p" >&2
return 1
fi
if [[ "$ONLY_REAL_FILES" == "yes" && ! -f "$p" ]]; then
continue
fi
if [[ "$DIFF_TO_BASE" ]]; then
older_copy="$DIFF_TO_BASE/$type/${p##*/}" # using shell param expansion instead of `basename' to speed up
if [[ -h "$older_copy" || -a "$older_copy" ]]; then
continue
fi
fi
allFiles[$(( no++ ))]="$p"
done
readonly -a allFiles
# Splitting the list of all files into future disks:
#
local -a filesToEat allSizes
let 'no = 0' ||:
filesToEat=()
allSizes=($(getSize "${allFiles[@]}"))
readonly -a allSizes
# allSizes contains the sizes corrsponding to allFiles
# filesToEat hold the constructed list of files to put on the current disk
# no points to the next free position in filesToEat
# totalSize should hold the sum of the sizes
# of the files already put into filesToEat;
# it is set and reset externally.
for p in "${allFiles[@]}"; do
if (( totalsize + ${allSizes[$(( no ))]} > CDVOLUME )); then
eatFiles "${filesToEat[@]}"
filesToEat=()
finishCD
startTypedCD
fi
let "totalsize += ${allSizes[$(( no ))]}" ||:
filesToEat[$(( no++ ))]="$p"
done
eatFiles "${filesToEat[@]}"
}
function eatFiles() {
#{ oldIFS="$IFS"; IFS=$'\n'; echo "$FUNCNAME: args: " "$*" | head >&2; IFS="$oldIFS"; }
zeroDelimited "$@" | xargs -0 --no-run-if-empty \
cp -s \
--target-dir="$THIS_LAYOUTS_DIR/cd$(( cdN ))/$PREFIX/$type$DOT_SUFFIX"/ \
--
}
function startTypedCD() {
# set -x
mkdir -p "$THIS_LAYOUTS_DIR/cd$(( cdN ))/$PREFIX/$type$DOT_SUFFIX"
start_action $" %s with %s" "$(( cdN ))" "$type"
# set +x
}
function finishCD() {
( 454. satırdan sonra daha fazlasını okuyun )
eatFiles
Fonksiyonun, gelecekteki disklerin yerleşimlerini, yaprakların gerçek dosyalara sembolik olduğu ağaçlar olarak hazırladığını unutmayın . Bu nedenle, yazdırmadan önce düzenleri düzenleyebilmeniz gereksiniminizi karşılamaktadır. mkisofs
Yarar gerçekten kodunda kullanılır Sembolik takip için bir seçenek vardır benim mkiso
işlevi .
Sunulan komut dosyası (elbette ihtiyaçlarınıza göre ve yeniden yazabilirsiniz!) En basit fikri takip eder: dosyaların boyutlarını (veya daha doğrusu, paketlerdeki paketleri distribute
) sadece listelendikleri sırayla toplamak için , herhangi bir yeniden düzenleme yapmayın.
"Otostopçunun Haskell rehberi" optimizasyon problemini daha ciddiye alır ve disklere daha iyi uymaları (ve daha az disk gerektirmeleri) için dosyaları akıllıca yeniden düzenlemeye çalışacak program varyantlarını önerir:
Zaten yeterince ön hazırlık. hadi bazı CD'leri paketleyelim.
Zaten fark etmiş olabileceğiniz gibi, sorunumuz klasik bir sorundur. Buna "sırt çantası sorunu" denir
( zaten ne olduğunu bilmiyorsanız google it up . 100000'den fazla bağlantı var).
açgözlü çözümden başlayalım ...
( Bölüm 3 ve daha fazlasında daha fazla bilgi edinin .)
Diğer akıllı araçlar
Ayrıca Debian'ın benim distribute
wrt paket koleksiyonumdan daha akıllı olan dağıtım CD'lerini yapmak için bir araç kullandığı söylendi : sonuçları daha iyi çünkü paketler arası bağımlılıkları önemsiyor ve paketlerin toplanmasını yapmaya çalışıyor ilk disk bağımlılıklar altında kapatılır, yani 1. diskteki hiçbir paket başka bir diskten bir paket gerektirmez (ya da en azından söyleyebilirim, bu tür bağımlılıkların sayısı en aza indirilmelidir).