हमें यह नहीं भूलना चाहिए कि कार्य का सार वास्तव में काफी सरल है; जैसा कि हास्केल पर एक ट्यूटोरियल में रखा गया है (जो इस कार्य के लिए समाधान के माध्यम से काम के आसपास लिखा गया है, वृद्धिशील रूप से परिष्कृत)
अब आइए एक पल के लिए सोचें कि हमारा कार्यक्रम कैसे संचालित होगा और इसे छद्मकोड में व्यक्त करेंगे:
main = Read list of directories and their sizes.
Decide how to fit them on CD-Rs.
Print solution.
उचित लगता है? मुझे ऐसा लगा।
आइए अपने जीवन को थोड़ा सरल करें और अभी के लिए मान लें कि हम अपने कार्यक्रम के बाहर निर्देशिका आकार की गणना करेंगे (उदाहरण के लिए, " du -sb *
") और स्टड से इस जानकारी को पढ़ें।
( सहयात्री गाइड से हास्केल, अध्याय 1 )
(अतिरिक्त, आपके प्रश्न में, आप परिणामी डिस्क लेआउट को ट्वीक (संपादित करना) कर सकते हैं, और फिर उन्हें जलाने के लिए एक उपकरण का उपयोग कर सकते हैं।)
आप अपने फ़ाइल संग्रह को विभाजित करने के लिए उस हास्केल ट्यूटोरियल से प्रोग्राम का एक सरल संस्करण फिर से उपयोग (अनुकूलित और पुनः उपयोग) कर सकते हैं।
दुर्भाग्य से, जिस distribute
उपकरण में मैंने यहां एक अन्य उत्तर में उल्लेख किया है , आवश्यक विभाजन कार्य की सादगी उपयोगकर्ता इंटरफ़ेस की जटिलता और सूजन से मेल नहीं खाती है distribute
(क्योंकि यह कई कार्यों को संयोजित करने के लिए लिखा गया था; हालांकि चरणों में प्रदर्शन किया गया था; लेकिन अभी भी सबसे स्वच्छ तरीके से संयुक्त नहीं हूं जो मैं अभी सोच सकता हूं)।
आपको इसके कोड का कुछ उपयोग करने में मदद करने के लिए, यहां 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
फ़ंक्शन भविष्य के डिस्क को उन पेड़ों के रूप में तैयार करता है जहां पत्ते वास्तविक फ़ाइलों के लिए सीमलिंक होते हैं। तो, यह आपकी आवश्यकता को पूरा कर रहा है कि आपको जलने से पहले लेआउट को संपादित करने में सक्षम होना चाहिए। mkisofs
उपयोगिता जो वास्तव में के कोड में कार्यरत है सिमलिंक पालन करने के लिए एक विकल्प है, मेरी mkiso
समारोह ।
प्रस्तुत स्क्रिप्ट (जिसे आप अपनी आवश्यकताओं के लिए ले सकते हैं और फिर से लिख सकते हैं!) सरलतम विचार का अनुसरण करते हैं: फाइलों के आकार (या, अधिक सटीक रूप से, पैकेज के मामले में distribute
) के लिए बस जिस क्रम में वे सूचीबद्ध थे, डॉन किसी भी व्यवस्था नहीं करते।
"हिचहाइकर्स गाइड टू हास्केल" अनुकूलन समस्या को अधिक गंभीरता से लेता है और प्रोग्राम वेरिएंट का सुझाव देता है जो फाइलों को स्मार्ट तरीके से फिर से व्यवस्थित करने की कोशिश करेंगे, ताकि वे डिस्क पर बेहतर फिट हो सकें (और कम डिस्क की आवश्यकता होती है):
पहले से ही पर्याप्त हैं। चलो कुछ सीडी पैक करते हैं।
जैसा कि आप पहले ही पहचान चुके होंगे, हमारी समस्या एक शास्त्रीय है। यह एक कहा जाता है "नेप्सेक समस्या"
( यह गूगल , यदि आप नहीं जानते कि यह पहले से ही क्या है। 100000 से अधिक लिंक कर रहे हैं)।
आइए लालची समाधान से शुरू करें ...
( अध्याय 3 और आगे में पढ़ें ।)
अन्य स्मार्ट उपकरण
मुझे यह भी बताया गया है कि डेबियन अपने डिस्ट्रो सीडी बनाने के लिए एक टूल का उपयोग करता है जो distribute
पैकेजों के मेरे wrt संग्रहों की तुलना में अधिक स्मार्ट है : इसके परिणाम अच्छे हैं क्योंकि यह अंतर-पैकेज निर्भरता के बारे में परवाह करता है और उन पैकेजों के संग्रह को बनाने की कोशिश करेगा जो उस पर मिलता है पहली डिस्क निर्भरता के तहत बंद हुई, अर्थात, 1 डिस्क से किसी भी पैकेज को दूसरे डिस्क से पैकेज की आवश्यकता नहीं होनी चाहिए (या कम से कम, मैं कहूंगा, ऐसी निर्भरता की संख्या कम से कम होनी चाहिए)।