เราไม่ควรลืมว่าสาระสำคัญของงานนั้นค่อนข้างง่าย ใส่ในการสอนเกี่ยวกับ Haskell (ซึ่งเขียนรอบการทำงานผ่านการแก้ปัญหาสำหรับงานนี้การปรับปรุงทีละน้อย)
ตอนนี้ลองคิดดูสักครู่ว่าโปรแกรมของเราจะทำงานอย่างไรและแสดงเป็น pseudocode:
main = Read list of directories and their sizes.
Decide how to fit them on CD-Rs.
Print solution.
ฟังดูสมเหตุสมผลหรือไม่ ฉันคิดอย่างนั้น
มาทำให้ชีวิตของเราง่ายขึ้นเล็กน้อยและสมมติว่าตอนนี้เราจะคำนวณขนาดไดเรกทอรีบางแห่งนอกโปรแกรมของเรา (เช่นด้วย " du -sb *
") และอ่านข้อมูลนี้จาก stdin
(จากHitchhikers แนะนำสู่ Haskell ตอนที่ 1 )
(นอกจากนี้ในคำถามของคุณคุณต้องการที่จะสามารถปรับแต่ง (แก้ไข) รูปแบบดิสก์ที่เกิดจากนั้นใช้เครื่องมือในการเผาไหม้พวกเขา)
คุณสามารถนำกลับมาใช้ใหม่ (ดัดแปลงและนำกลับมาใช้ใหม่) ได้อย่างง่าย ๆ จากโปรแกรม Haskell เพื่อการแบ่งไฟล์ของคุณ
แต่น่าเสียดายที่ในเครื่องมือที่ผมเคยกล่าวถึงที่นี่ในคำตอบอื่น , ความเรียบง่ายของงานแยกที่สำคัญไม่ตรงกับความซับซ้อนและ bloatedness ของอินเตอร์เฟซผู้ใช้(เพราะมันถูกเขียนขึ้นเพื่อรวมงานหลายแห่งแม้จะดำเนินการในขั้นตอน แต่ยังรวมกันไม่ได้ในวิธีที่สะอาดที่สุดที่ฉันสามารถคิดได้ในขณะนี้)distribute
distribute
เพื่อช่วยให้คุณใช้ประโยชน์จากรหัสของมันนี่คือข้อความที่ตัดตอนมาจาก bash-code ของdistribute
(ที่บรรทัดที่ 380 ) ที่ทำหน้าที่ "จำเป็น" นี้ในการแยกไฟล์:
# 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 )
โปรดทราบว่าeatFiles
ฟังก์ชั่นเตรียมเค้าโครงของดิสก์ในอนาคตเป็นแผนผังซึ่งใบไม้เป็น symlink ไปยังไฟล์จริง ดังนั้นจึงเป็นไปตามความต้องการของคุณที่คุณควรจะสามารถแก้ไขเลย์เอาต์ก่อนที่จะเขียน mkisofs
ยูทิลิตี้มีตัวเลือกที่จะปฏิบัติตาม symlinks ซึ่งเป็นลูกจ้างแน่นอนในรหัสของฉันmkiso
ฟังก์ชั่น
สคริปต์ที่นำเสนอ (ซึ่งคุณสามารถนำไปใช้และเขียนซ้ำตามความต้องการของคุณ!) ตามความคิดที่ง่ายที่สุด: เพื่อรวมขนาดของไฟล์ (หรือแม่นยำยิ่งขึ้นแพ็คเกจในกรณีของdistribute
) เพียงในลำดับที่พวกเขาอยู่ในรายการอย่า ไม่ต้องจัดเรียงใหม่
"Hitchhikers guide to Haskell" ให้ความสำคัญกับปัญหาการปรับให้เหมาะสมที่สุดและแนะนำตัวแปรของโปรแกรมที่จะพยายามจัดเรียงไฟล์ใหม่อย่างชาญฉลาดเพื่อให้พวกเขาสามารถใส่ดิสก์ได้ดีขึ้น
เพียงพอเบื้องต้นแล้ว ไปเก็บซีดีกันบ้าง
ในขณะที่คุณอาจได้รับการยอมรับปัญหาของเราเป็นคลาสสิก มันถูกเรียกว่า"ปัญหาเป้"
( googleถ้าคุณไม่ทราบว่ามันคืออะไรมีมากกว่า 100,000 ลิงก์)
เริ่มจากทางออกโลภ ...
(อ่านเพิ่มเติมในบทที่ 3ขึ้นไป)
เครื่องมืออัจฉริยะอื่น ๆ
ฉันได้รับการบอกด้วยว่า Debian ใช้เครื่องมือในการทำซีดี distro ที่ฉลาดกว่าdistribute
ชุด wrt ของฉัน: ผลลัพธ์ของมันดีกว่าเพราะมันให้ความสำคัญกับการพึ่งพาระหว่างแพ็กเกจและจะพยายามรวบรวมชุดที่ได้รับ ดิสก์แรกที่ปิดอยู่ภายใต้การอ้างอิงคือไม่มีแพ็คเกจจากดิสก์ที่ 1 ควรต้องใช้แพคเกจจากดิสก์อื่น