एक संभावित विशाल फ़ाइल से n यादृच्छिक लाइनें पढ़ें


17

यह चुनौती पूरी फ़ाइल को मेमोरी में पढ़े बिना संभावित रूप से विशाल फ़ाइल से यादृच्छिक लाइनें पढ़ने के बारे में है।

इनपुट

एक पूर्णांक nऔर एक पाठ फ़ाइल का नाम।

उत्पादन

n प्रतिस्थापन के बिना पाठ फ़ाइल की लाइनें समान रूप से यादृच्छिक रूप से चुनी गई हैं।

आप मान सकते हैं कि nफ़ाइल में लाइनों की संख्या 1 से सीमा तक है।

जब nआप जो उत्तर प्राप्त करते हैं उस क्रम से यादृच्छिक पर संख्याओं का नमूना करते समय सावधान रहें । rand()%nसी में उदाहरण के लिए एक समान नहीं है। हर परिणाम समान रूप से होने की संभावना है।

नियम और प्रतिबंध

पाठ फ़ाइल की प्रत्येक पंक्ति में समान वर्ण होंगे और यह संख्या 80 से अधिक नहीं होगी।

आपके कोड को छोड़कर टेक्स्ट फ़ाइल की कोई सामग्री नहीं पढ़नी चाहिए:

  • उन लाइनों यह आउटपुट।
  • पाठ फ़ाइल में प्रति पंक्ति कितने वर्ण हैं, यह जानने के लिए पहली पंक्ति।

हम मान सकते हैं कि पाठ फ़ाइल में प्रत्येक वर्ण बिल्कुल एक बाइट लेता है।

लाइन विभाजकों को 1 बाइट लंबा माना जाता है। समाधान 2 बाइट लंबी लाइन विभाजक का उपयोग कर सकते हैं केवल अगर वे इस आवश्यकता को निर्दिष्ट करते हैं। आप यह भी मान सकते हैं कि अंतिम लाइन एक लाइन विभाजक द्वारा समाप्त हो गई है।

आपका उत्तर पूर्ण कार्यक्रम होना चाहिए लेकिन आप इनपुट को किसी भी तरह से निर्दिष्ट कर सकते हैं जो सुविधाजनक हो।

भाषाएं और पुस्तकालय

आप अपनी पसंद की किसी भी भाषा या लाइब्रेरी का उपयोग कर सकते हैं।

टिप्पणियाँ

फ़ाइल में लाइनों की संख्या की गणना करने के बारे में एक चिंता थी। जैसा कि निमि टिप्पणियों में बताते हैं, आप इसे फ़ाइल आकार और प्रति पंक्ति वर्णों की संख्या से अनुमान लगा सकते हैं।

प्रेरणा

चैट में कुछ लोगों ने पूछा कि क्या यह वास्तव में "वाई के बिना एक्स एक्स" सवाल है। मैं यह पूछने के लिए व्याख्या करता हूं कि क्या प्रतिबंध असामान्य रूप से कृत्रिम हैं।

बड़ी फ़ाइलों से यादृच्छिक रूप से नमूने लेने का कार्य असामान्य नहीं है और वास्तव में एक है जो मुझे कभी-कभी करना पड़ता है। ऐसा करने का एक तरीका है:

shuf -n <num-lines>

हालाँकि यह बड़ी फ़ाइलों के लिए बहुत धीमी है क्योंकि यह पूरी फ़ाइल में पढ़ती है।


क्यों होता है पतन?

3
यह सी जैसी भाषाओं में तुच्छ है fseek, और दूसरों में असंभव है। इसके अतिरिक्त, क्या होगा अगर nफ़ाइल में लाइनों की संख्या से अधिक है?
मेगो

4
@Mego: अपनी बात के बारे में b): आप एक पंक्ति की लंबाई से फ़ाइल के आकार को विभाजित करके लाइनों की संख्या की गणना कर सकते हैं।
nimi

8
Do X बिना Y एक चेतावनी है जो "यह हमेशा बुरा नहीं होता है" से शुरू होता है। मुख्य समस्या कृत्रिम प्रतिबंध जैसे "उपयोग न करना" है जो उन भाषाओं को लाभ देता है जिनके पास ए है sum()। फ़ाइल को मेमोरी में न पढ़ना एक स्पष्ट और सुसंगत प्रतिबंध है जो किसी भी तरह से मनमाना नहीं है। इसे मेमोरी से बड़ी फ़ाइल के साथ टेस्ट किया जा सकता है, जिसे भाषा के अंतर से काम नहीं किया जा सकता है। यह वास्तविक विश्व अनुप्रयोगों के लिए भी होता है (हालांकि यह गोल्फ के लिए आवश्यक नहीं है ...)।
ट्राइकोप्लेक्स

1
ऐसा लगता है कि यह वास्तव में एक प्रतिबंधित जटिलता कोड गोल्फ है जहां संभावित बड़ी फ़ाइलों के बावजूद मेमोरी का उपयोग सीमित है। यह आपके कोड में कुछ चीजों के नहीं होने के बारे में है, लेकिन इस बारे में एक सीमा है कि कोड कैसे कार्य कर सकता है।
xnor

जवाबों:


6

दिल्लोग एपीएल , 63 बाइट्स

⎕NREAD¨t 82l∘,¨lׯ1+⎕?(⎕NSIZE t)÷l←10⍳⍨⎕NREAD 83 80,⍨t←⍞⎕NTIE 0

फ़ाइल नाम के लिए संकेत, फिर कितनी यादृच्छिक लाइनें वांछित हैं।

व्याख्या

टेक्स्ट इनपुट के लिए प्रॉम्प्ट (फ़ाइल नाम)
⎕NTIE 0अगले उपलब्ध टाई नंबर (एक साफ सिस्टम पर -1 ) का उपयोग करके फ़ाइल
t←को टाई करें। चुने गए टाई नंबर को t
83 80,⍨एपेंड के रूप में स्टोर करें [83,80] उपज [-1,83,80]
⎕NREADपहले 80 बाइट पढ़ें फाइल -1 के रूप में 8-बिट पूर्णांक (रूपांतरण कोड 83)
10⍳⍨पहले नंबर 10 (एलएफ) के सूचकांक का पता लगाएं
l←लाइन की लंबाई को स्टोर करें l
(⎕NSIZE t)÷फ़ाइल के आकार को विभाजित करें -1 लाइन की लंबाई के साथ
संख्यात्मक इनपुट के लिए प्रॉम्प्ट (लाइनों की वांछित संख्या) )
?एक्स रैंडम सिलेक्शन (बिना रिप्लेसमेंट के) पहले Y नेचुरल नंबरों को बाहर कर दें
¯1+-1 को 0- ओरिजनल लाइन नंबर पाने के लिए -1 *
स्टार्ट बाइट्स को प्राप्त करने के लिए लाइन लेंथ से गुणा
t 82l∘,¨करें [प्रत्येक -1] के लिए प्रीपेंड [-1,82, लाइन लैंथ] के लिए तर्कों की सूची ⎕NREAD)
⎕NREAD¨ प्रत्येक पंक्ति को 8-बिट वर्ण (रूपांतरण कोड 82) के रूप में पढ़ें

व्यावहारिक उदाहरण

फ़ाइल /tmp/records.txt में शामिल हैं:

Hello
Think
12345
Klaus
Nilad

कार्यक्रम बनायें RandLines में उपरोक्त कोड को एपीएल सत्र में दर्ज करके शब्दशः शामिल हैं:

∇RandLines
⎕NREAD¨t 82l∘,¨lׯ1+⎕?(⎕NSIZE t)÷l←10⍳⍨⎕NREAD 83 80,⍨t←⍞⎕NTIE 0
∇

APL सत्र प्रकार में RandLinesऔर Enter दबाएँ।

सिस्टम कर्सर को अगली पंक्ति में ले जाता है, जो वर्ण डेटा के लिए 0-लंबाई संकेत है; दर्ज करें /tmp/records.txt

सिस्टम अब आउटपुट ⎕:और संख्यात्मक इनपुट का इंतजार कर रहा है; दर्ज करें 4

प्रणाली चार यादृच्छिक लाइनों का उत्पादन करती है।

असली जीवन

वास्तविकता में, आप फ़ाइल नाम देना और तर्क के रूप में गिनना और तालिका के रूप में परिणाम प्राप्त कर सकते हैं। यह दर्ज करके किया जा सकता है:

RandLs←{↑⎕NREAD¨t 82l∘,¨lׯ1+⍺?(⎕NSIZE t)÷l←10⍳⍨⎕NREAD 83 80,⍨t←⍵⎕NTIE 0}

अब आप MyLines के साथ तीन यादृच्छिक रेखाएँ बनाते हैं:

MyLines←3 RandLs'/tmp/records.txt'

यदि गणना निर्दिष्ट नहीं है, तो केवल एक ही यादृच्छिक लाइन वापस करने के बारे में कैसे:

RandL←{⍺←1 ⋄ ↑⎕NREAD¨t 82l∘,¨lׯ1+⍺?(⎕NSIZE t)÷l←10⍳⍨⎕NREAD 83 80,⍨t←⍵⎕NTIE 0}

अब आप दोनों कर सकते हैं:

MyLines←2 RandL'/tmp/records.txt'

और (बाएं तर्क की अनुपस्थिति नोटिस):

MyLine←RandL'/tmp/records.txt'

कोड को पठनीय बनाना

गोल्फ एपीएल वन-लाइनर्स एक बुरा विचार है। यहाँ मैं एक उत्पादन प्रणाली में कैसे लिखूंगा:

RandL←{ ⍝ Read X random lines from file Y without reading entire file
    ⍺←1 ⍝ default count
    tie←⍵⎕NTIE 0 ⍝ tie file
    length←10⍳⍨⎕NREAD 83 80,⍨tie ⍝ find first NL
    size←⎕NSIZE tie ⍝ total file length
    starts←lengthׯ1+⍺?size÷length ⍝ beginning of each line
    ↑⎕NREAD¨tie 82length∘,¨starts ⍝ read each line as character and convert list to table
}

* मैं 0-मूल मोड में चलकर एक बाइट को बचा सकता था, जो कुछ एपीएल सिस्टम पर मानक है: पहले निकालें ¯1+और डालें ।1+10


आह .. एपीएल :) क्या इस कोड को लिनक्स में परीक्षण करने का कोई तरीका है?

@Lembik ज़रूर, यह कोड क्रॉस प्लेटफॉर्म है। Dyalog.com
Adám

जैसा कि मैंने एपीएल नहीं पढ़ा है, क्या आप कोड समझा सकते हैं? मुश्किल भागों लाइनों नमूने कर रहे हैं बिना प्रतिस्थापन और लाइनों को पढ़ने के लिए फ़ाइल में सही जगह पर सीधे कूद।

@ लेम्बिक वह हिस्सा आसान है। ⎕NREAD का तर्क TieNumber ConvertCode BytesToRead [StartByte] है। यह सिर्फ आवश्यक बाइट्स पढ़ता है। बाकी अभी पता लगा रहे हैं कि क्या पढ़ना है।
आदम

@ लिम्बिक मैं उत्सुक हूं कि मेरा जवाब इनाम क्यों नहीं जीता।
एडम

7

रूबी, 104 94 92 90 बाइट्स

फ़ाइल नाम और लाइनों की संख्या कमांड लाइन में पारित की जाती है। उदाहरण के लिए, यदि प्रोग्राम है shuffle.rbऔर फ़ाइल का नाम है a.txt, ruby shuffle.rb a.txt 3तीन यादृच्छिक लाइनों के लिए चलाएँ ।

-4 बाइट्स के openबजाय रूबी में वाक्य रचना की खोज सेFile.new

f=open$*[0]
puts [*0..f.size/n=f.gets.size+1].sample($*[1].to_i).map{|e|f.seek n*e;f.gets}

इसके अलावा, यहां 85-बाइट अनाम फ़ंक्शन समाधान है जो एक स्ट्रिंग और संख्या को अपने तर्कों के रूप में लेता है।

->f,l{f=open f;puts [*0..f.size/n=f.gets.size+1].sample(l).map{|e|f.seek n*e;f.gets}}

नीचे 100 बाइट्स! शायद रूबी सब के बाद सबसे अच्छी गोल्फिंग भाषा है। क्या 'नमूना' दोहराव से बचता है?

@Lembik ruby-doc.org/core-2.2.0/Array.html#method-i-sample यह दोहराव से बचता है। मुझे मत बताना ... क्या मुझे पुनरावृत्तियाँ मिलने वाली थीं?
वैल्यू इंक

नहीं आप सही हैं :)

क्या आप स्टड से पढ़कर किसी भी बाइट को बचा सकते हैं? ruby shuffle.rb 3 < a.txtआप एक खोज योग्य स्टड देता है। आईडीके रूबी, हालांकि।
पीटर कॉर्ड्स

1
@PeterCordes जो समझ में आता है, लेकिन जैसा कि उल्लेख किया गया है, विफलता का बिंदु रूबी है जो स्टडिन के फ़ाइल आकार को पढ़ने में असमर्थ है, इसलिए यह काम नहीं किया।
वैल्यू इंक

5

हास्केल, 240 224 236 बाइट्स

import Test.QuickCheck
import System.IO
g=hGetLine
main=do;f<-getLine;n<-readLn;h<-openFile f ReadMode;l<-(\x->1+sum[1|_<-x])<$>g h;s<-hFileSize h;generate(shuffle[0..div s l-1])>>=mapM(\p->hSeek h(toEnum 0)(l*p)>>g h>>=putStrLn).take n

स्टड से फ़ाइल नाम और एन पढ़ता है।

यह काम किस प्रकार करता है:

main=do
  f<-getLine                   -- read file name from stdin
  n<-readLn                    -- read n from stdin
  h<-openFile f ReadMode       -- open the file
  l<-(\x->1+sum[1|_<-x])<$>g h -- read first line and bind l to it's length +1
                               -- sum[1|_<-x] is a custom length function
                               -- because of type restrictions, otherwise I'd have
                               -- to use "toInteger.length"
  s<-hFileSize h               -- get file size
  generate(shuffle[0..div s l-1])>>=
                               -- shuffle all possible line numbers 
  mapM (\->p  ...  ).take n    -- for each of the first n shuffled line numbers 
     hSeek h(toEnum 0).(l*p)>> -- jump to that line ("toEnum 0" is short for "AbsoluteSeek")
     g h>>=                    -- read a line from current position
     putStrLn                  -- and print

एक भयानक अक्षम्य shuffleफ़ंक्शन के कारण, कई लाइनों वाली फ़ाइलों के लिए इस कार्यक्रम को चलाने में बहुत समय और मेमोरी लगती है ।

संपादित करें: मैं "बिना प्रतिस्थापन के यादृच्छिक" भाग से चूक गया (धन्यवाद @ Faersum for noticing!)।


हास्केल चट्टानों :)

1
यह एक लाइन चुनने से कैसे बचता है जो पहले से ही चुना गया था?
फेरेसम

@ फैर्सम: ओह, मैं उस हिस्से को याद कर रहा हूं। फिक्स्ड।
nimi

मैं देखता हूं कि stackoverflow.com/questions/13779630/… कुछ हद तक क्रिया है!

1
हो सकता है कि छोटे स्थान पर प्रतिस्थापन के बिना नमूने पर एक अलग चुनौती होनी चाहिए।

3

PowerShell v2 +, 209 बाइट्स

param($a,$n)
$f=New-Object System.IO.FileStream $a,"Open"
for(;$f.ReadByte()-ne10){$l++}
$t=$f.Length/++$l-1
[byte[]]$z=,0*$l
0..$t|Get-Random -c $n|%{$a=$f.Seek($l*$_,0);$a=$f.Read($z,0,$l-1);-join[char[]]$z}

$aफ़ाइल नाम और $nलाइनों की संख्या के रूप में इनपुट लेता है । ध्यान दें कि $aएक पूर्ण-पथ फ़ाइल नाम होना चाहिए, और ANSI एन्कोडिंग होना माना जाता है।

हम फिर एक नई FileStreamवस्तु का निर्माण करते हैं , और इसे विशेषाधिकार के $aसाथ फ़ाइल तक पहुंचने के लिए कहते हैं Open

forपाश .Read()जब तक हम एक हिट पहली पंक्ति के माध्यम से है \nचरित्र, हमारी लाइन-लेंथ काउंटर हर किरदार incrementing। हम फिर $tफ़ाइल के आकार के बराबर सेट करते हैं (यानी, स्ट्रीम कितनी लंबी है) को प्रति लाइन कितने वर्णों से विभाजित किया जाता है (प्लस एक तो यह टर्मिनेटर को गिना जाता है), माइनस एक (क्योंकि हम शून्य-अनुक्रमित हैं)। फिर हम अपने बफर $zका निर्माण लाइन की लंबाई के लिए भी करते हैं।

अंतिम पंक्ति ..रेंज ऑपरेटर के साथ एक गतिशील सरणी का निर्माण करती है । 1 हम पुनरावृत्ति के बिना लाइन संख्या को बेतरतीब ढंग से चयन करने के लिए Get-Randomएक सरणी के साथ उस सरणी को पाइप करते हैं । भाग्यशाली संख्याओं को एक लूप में पाइप किया जाता है । प्रत्येक पुनरावृत्ति हम विशेष स्थान के लिए, और फिर एक पंक्ति में पात्र के मूल्य में संग्रहीत है । हम एक चार-सरणी के रूप में फिर से कास्ट करते हैं और यह एक साथ पाइप लाइन पर परिणामी स्ट्रिंग को छोड़ देता है और आउटपुट कार्यक्रम के अंत में निहित होता है।-C$n$n|%{...}.Seek.Read$z$z-join

तकनीकी रूप से हमें $f.Close()फ़ाइल को बंद करने के लिए कॉल के साथ समाप्त होना चाहिए , लेकिन इसकी लागत बाइट्स है! : p

उदाहरण

a.txt:
a0000000000000000000000000000000000000000000000001
a0000000000000000000000000000000000000000000000002
a0000000000000000000000000000000000000000000000003
a0000000000000000000000000000000000000000000000004
a0000000000000000000000000000000000000000000000005
a0000000000000000000000000000000000000000000000006
a0000000000000000000000000000000000000000000000007
a0000000000000000000000000000000000000000000000008
a0000000000000000000000000000000000000000000000009
a0000000000000000000000000000000000000000000000010

PS C:\Tools\Scripts\golfing> .\read-n-random-lines.ps1 "c:\tools\scripts\golfing\a.txt" 5
a0000000000000000000000000000000000000000000000002 
a0000000000000000000000000000000000000000000000001 
a0000000000000000000000000000000000000000000000004 
a0000000000000000000000000000000000000000000000010 
a0000000000000000000000000000000000000000000000006 

1 तकनीकी रूप से, इसका मतलब है कि हम केवल अधिकतम 50,000 लाइनों का समर्थन कर सकते हैं, क्योंकि यह सबसे बड़ी सीमा है जिसे इस तरीके से गतिशील रूप से बनाया जा सकता है। : - / लेकिन, हम न सिर्फ पाश एक कर सकते हैं Get-Randomकमान $nबार, डुप्लिकेट प्रत्येक पाश को त्यागकर, क्योंकि ऐसा करना निर्धारित करने योग्य नहीं है ...


2

पायथन 3, 146 139 बाइट्स

from random import*
i=input
f=open(i())
l=len(f.readline())
[(f.seek(v*l),print(f.read(l)))for v in sample(range(f.seek(0,2)//l),int(i()))]
#print is here^

इनपुट: [फ़ाइल नाम] \ n [लाइनें] \ n

यह समाधान @pppery से बहुत अधिक चुराया गया है लेकिन केवल python3.5 है और एक पूर्ण कार्यक्रम है।

संपादित करें: इनलाइन रेंज और python3.x संगतता के लिए @Mego का धन्यवाद। Edit2: स्पष्टिकरण जहां प्रिंट है क्योंकि मुझे इसके बारे में दो टिप्पणियां मिली हैं। (टिप्पणी स्पष्ट रूप से कोड या बाइट गिनती का हिस्सा नहीं है।)


धन्यवाद! अजगर 3.5 किस भाग में है?

2
r=range(f.seek(0,2)//l)काम करेगा, जो 3 बाइट्स को बंद कर देता है और 3.5 की आवश्यकता को हटा देता है। और भी बेहतर, rangeकॉल में कॉल को इनलाइन करके 3 और बाइट्स को शेव sampleकरें। इसके अतिरिक्त, यह एक पूर्ण कार्यक्रम नहीं है - आपको वास्तव में सूची को प्रिंट करने की आवश्यकता है।
Mego

@ लेम्बिक: यह केवल 3.5 था क्योंकि मैंने इसका इस्तेमाल किया r=[*range(f.seek(0,2)//l)]क्योंकि मुझे लगा कि मैं sampleएक जनरेटर नहीं बना सकता । मैं बाहर कर सकता है। @Mega: यह पूरा हो गया है क्योंकि यह सूची समझ के अंदर हर पंक्ति को प्रिंट करता हैprint(f.read(l))
अलेक्जेंडर निगेल

हालांकि आपको एक प्रिंट स्टेटमेंट की जरूरत है।

प्रिंट सूची समझ के अंदर है।
अलेक्जेंडर निगल

2

लूआ, 126 122

r=io.read;f=io.open(r())c=2+f:read():len()for i=1,r()do f:seek("set",c*math.random(0,f:seek("end")/c-1))print(f:read())end

लाइन ब्रेक के लिए 2 बाइट्स का उपयोग करता है। 2 को 1 के लिए 1 में बदलें। मेरे पास केवल 2 के रूप में है क्योंकि यही मेरी टेस्ट फाइल थी।

PHP प्रविष्टि के तहत खुद को मिला, लेकिन अभी भी 2 स्थान (वर्तमान में)। शुक्रिया, रूबी प्रवेश!


1
Lua पहली प्रोग्रामिंग भाषा थी जिसे मैंने सीखा था, और तब से मैंने जो कुछ भी सीखा है, वह अभी भी मेरी पसंदीदा है। यह लिखने में आसानी के लिए बस इतना बहुमुखी है।
ब्लाब

2

बैश (अच्छी तरह से, कोरुटिल्स), 100 बाइट्स

n=`head -1 $2|wc -c`;shuf -i0-$[`stat -c%s $2`/$n] -n$1|xargs -i dd if=$2 bs=$n skip={} count=1 2>&-

व्याख्या

यह ddपूरी तरह से फ़ाइल को पढ़ने के बिना हमें जिस फ़ाइल की आवश्यकता है, उसके हिस्से को निकालने के लिए पूरी फाइल को पढ़ने से बचा जाता है , दुर्भाग्य से यह हमारे द्वारा निर्दिष्ट सभी विकल्पों के साथ काफी बड़ा है।

ifक्या इनपुट फ़ाइल
bsब्लॉक आकार है (यहां हमने इसे सेट किया है, $nजिसकी पहली पंक्ति की लंबाई
skipयादृच्छिक पूर्णांक से निकाली गई है shufऔर ibsमान स्किपिंग के बराबर है skip* ibsबाइट्स वापस लौटने के लिए लंबाई वर्गों
countकी संख्या की आवश्यकता होती है जानकारी सामान्य रूप से द्वारा उत्पादनibs
status=nonedd

हम लाइन की लंबाई का उपयोग कर head -1 $2|wc -cऔर फ़ाइलों के साथ मिलता है stat -c%s $2

प्रयोग

ऊपर के रूप में सहेजें file.shऔर उपयोग कर चलाएं file.sh n filename

समय

time ~/randlines.sh 4 test.txt
9412647
4124435
7401105
1132619

real    0m0.125s
user    0m0.035s
sys     0m0.061s

बनाम

time shuf -n4 test.txt
1204350
3496441
3472713
3985479

real    0m1.280s
user    0m0.287s
sys     0m0.272s

एक 68MiB फ़ाइल का उपयोग कर उत्पन्न के लिए ऊपर टाइम्स seq 1000000 9999999 > test.txt

उनके -1 टिप के लिए @PeterCordes को धन्यवाद !


1
मुझे हमेशा एक बाश जवाब पसंद है लेकिन क्या आप बता सकते हैं कि यह पूरी फाइल को कैसे नहीं पढ़ता है?

2
@Lembik ने जोड़ा स्पष्टीकरण!
डोम हेस्टिंग्स

1
आप bs=इसके बजाय कर सकते हैं ibs=, क्योंकि सेटिंग obsठीक है। मुझे लगता है कि आप इसके if=$2साथ प्रतिस्थापित नहीं कर सकते <$2, क्योंकि यह अभी भी xargsकमांड लाइन है। \<$2या तो काम नहीं करता (xargs सीधे निष्पादन का उपयोग करता है, बिना शेल के)।
पीटर कॉर्डेस

मुझे आशा है कि यह बहुत ज्यादा नहीं है, लेकिन मुझे इस जवाब से प्यार है :) बस इसे 1 जीबी फ़ाइल के साथ जांचा।

1
पुन: स्टडर्न को स्ट्रीडर पर पुनर्निर्देशित करना: आप स्टैडर को भी बंद कर सकते हैं 2>&-, इसलिए आउटपुट के कहीं भी चले जाने का कोई खतरा नहीं है (जैसे अगर स्टडिन एक रीड-राइट फ़ाइल डिस्क्रिप्टर हुआ)। यह GNU के साथ काम करता है dd: यह अभी भी stdoutलिखने की कोशिश करने और असफल होने से पहले इसका उत्पादन करता है stderr
पीटर कॉर्ड्स

1

पायथन 3 - 161 160 149 बाइट्स

from random import*;
def f(n,g):f=open(g);l=len(f.readline());r=list(range(f.seek(0,2)/l));shuffle(r);[(f.seek(v*l),print(f.read(l)))for v in r[:k]]

यह कोड एक फ़ंक्शन को परिभाषित करता है जिसे कहा जाता है f(10,'input.txt')


1
चुनौती के लिए एक पूर्ण कार्यक्रम की आवश्यकता होती है, इसलिए मुझे डर है कि कोई फ़ंक्शन परिभाषा पर्याप्त नहीं है।
nimi

आयात और * के बीच बाइट हटाने के स्थान को बचाने के लिए।
mriclojn

1
@nimi इस चुनौती के लिए एक पूर्ण कार्यक्रम की आवश्यकता प्रतीत हो रहा है arbitarily डिफ़ॉल्ट कोड प्रारूप नियमों अधिभावी
pppery

@ppperry: हाँ, हो सकता है, लेकिन यह सिर्फ यह कैसे है।
nimi

फ़ाइल की लंबाई पाने के लिए आप f.seek (0,2) कर सकते हैं , जिससे आयात os और os.stat अप्रचलित हो जाता है।
अलेक्जेंडर निगल

1

डुप्लिकेट के बिना C # 259 बाइट्स

class Program{static void Main(string[]a){int c=Convert.ToInt32(a[1]);var h=File.ReadLines(a[0]);HashSet<int>n=new HashSet<int>();while(n.Count<c)n.Add(new Random().Next(0,h.Count()));for(;c>0;c--)Console.WriteLine(h.Skip(n.ElementAt(c-1)).Take(1).First());}}

Ungolfed

class Program{static void Main(string[] a)
{
        int c = Convert.ToInt32(a[1]);
        var h = File.ReadLines(a[0]);
        HashSet<int> n = new HashSet<int>();
        while (n.Count < c)
            n.Add(new Random().Next(0, h.Count()));           
        for (; c > 0; c--)
            Console.WriteLine(h.Skip(n.ElementAt(c-1)).Take(1).First());
    }
}

File.ReadLines आलसी है। इसका अतिरिक्त लाभ यह है कि सभी लाइनों की लंबाई अलग-अलग हो सकती है।

यह चल रहा होगा:

sample.exe a.txt 10000

डुप्लिकेट के साथ C # 206 बाइट्स

class Program{static void Main(string[]a){var n=new Random();int c=Convert.ToInt32(a[1]);var h=File.ReadLines(a[0]);for(;c>0;c--)Console.WriteLine(h.Skip((int)(n.NextDouble()*h.Count())).Take(1).First());}}

Ungolfed

class Program
{
    static void Main(string[] a)
    {
        Random n = new Random();
        int c = Convert.ToInt32(a[1]);
        var h = File.ReadLines(a[0]);
        for (; c > 0; c--)
            Console.WriteLine(h.Skip((int)(n.NextDouble()*h.Count())).Take(1).First());
    }
}

मैं आपके समाधान का पूरी तरह पालन नहीं करता हूं। यदि सभी लाइनों में अलग-अलग लंबाई है तो कार्य असंभव है। इसके अलावा, कैसे आप प्रतिस्थापन के बिना बेतरतीब ढंग से नमूने लाइनों रहे हैं? मैं माफी माँगता हूँ मेरा सी # काफी अच्छा नहीं है।

@Lembik आप सही हैं, मैंने डुप्लिकेट के बारे में नहीं सोचा था। और मैं रेखाओं की मात्रा की गणना कर सकता हूं और लिननम्बर द्वारा लाइनें निकाल सकता हूं, यही वजह है कि लाइनें वैरिएबल लेन हो सकती हैं।
मास्टर ११7

लेकिन आपको फ़ाइल में एक स्थान पर कूदना होगा केवल यह जानने के लिए कि क्या लाइन नंबर नहीं है? आप यह नहीं बता सकते हैं कि जब तक कि सभी लाइनों की लंबाई समान नहीं होती है।

@Lembik File.ReadLines ("pathToFile") फ़ाइल की सभी लाइन्स, File.ReadLines ("pathToFile") पर एक आलसी एन्यूमरेशन बनाता है। elementAt (19) फ़ाइल की 19 वीं लाइन देता है। सभी Linestarts के एक नक्शे की तरह Kinda।
मास्टर ११7

मुझे नहीं लगता है कि आलसी एन्यूमरेशन कूदता है (या चाहता है) दुख की बात है। इसलिए यह वर्तमान में नियमों के अनुकूल नहीं है।

1

पायथन (141 बाइट्स)

प्रत्येक लाइन को समान संभावना के साथ रखता है, पाइप के साथ भी उपयोग करें। हालांकि यह सवाल के आगे सीमा को छोड़ जवाब नहीं है ...

प्रयोग cat largefile | python randxlines.py 100 या python randxlines 100 < largefile(@petercordes ने बताया)

import random,sys
N=int(sys.argv[1])
x=['']*N
for c,L in enumerate(sys.stdin):
    t=random.randrange(c+1)
    if(t<N):x[t] = L
print("".join(x))

3
इस सवाल का पूरा मुद्दा यह है कि आपको इनपुट स्ट्रीम में तलाश करना होगा। आपको शायद यह कहना चाहिए कि यह आपके द्वारा अनदेखा किए जा रहे प्रश्न के प्रतिबंध का हिस्सा है (हालांकि पढ़ने-से-पाइप उदाहरण के उपयोग से यह बहुत स्पष्ट हो जाता है)। स्टड के साथ पढ़ना python ./randxlines.py 100 < largefileएक उचित उत्तर के लिए ठीक होगा, हालांकि: उस मामले में खोज योग्य stdinहोगा।
पीटर कॉर्ड्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.