একটি সম্ভাব্য বিশাল ফাইল থেকে এন এলোমেলো লাইন পড়ুন


16

এই চ্যালেঞ্জটি সম্পূর্ণ ফাইলটিকে মেমরির মধ্যে না পড়েই সম্ভাব্য বিশাল ফাইল থেকে এলোমেলো লাইন পড়ার বিষয়ে।

ইনপুট

একটি পূর্ণসংখ্যা nএবং একটি পাঠ্য ফাইলের নাম।

আউটপুট

n পাঠ্য ফাইলের লাইনগুলি প্রতিস্থাপন ছাড়াই এলোমেলোভাবে পছন্দ করে।

আপনি ধরে নিতে পারেন n ফাইলটির লাইন সংখ্যা থেকে 1 এর মধ্যে রয়েছে।

nআপনি যে উত্তরটি পেয়েছেন তা অভিন্ন বলে পরিসীমা থেকে এলোমেলোভাবে সংখ্যার নমুনা দেওয়ার সময় সাবধান হন। rand()%nসি উদাহরণস্বরূপ অভিন্ন নয়। প্রতিটি ফলাফল সমান সম্ভাবনা হতে হবে।

বিধি এবং বিধিনিষেধ

পাঠ্য ফাইলের প্রতিটি লাইনে একই সংখ্যার অক্ষর থাকবে এবং এটি 80 এর বেশি হবে না।

আপনার কোড অবশ্যই পাঠ্য ফাইলের যে কোনও বিষয়বস্তু পড়তে হবে না:

  • এই লাইন এটি আউটপুট।
  • পাঠ্য ফাইলে প্রতি লাইনে কত অক্ষর রয়েছে তা নিয়ে কাজ করার জন্য প্রথম লাইন।

আমরা অনুমান করতে পারি পাঠ্য ফাইলের প্রতিটি অক্ষর ঠিক এক বাইট লাগে takes

লাইন বিভাজকগুলি 1 বাইট দীর্ঘ বলে ধরে নেওয়া হয়। সমাধানগুলি 2 বাইট দীর্ঘ লাইন বিভাজক ব্যবহার করতে পারে কেবল যদি তারা এই প্রয়োজনটি নির্দিষ্ট করে। আপনি ধরে নিতে পারেন যে শেষ লাইনটি কোনও লাইন বিভাজক দ্বারা সমাপ্ত হয়।

আপনার উত্তরটি একটি সম্পূর্ণ প্রোগ্রাম হওয়া উচিত তবে আপনি যে কোনও উপায়ে সুবিধাজনকভাবে ইনপুট নির্দিষ্ট করতে পারেন।

ভাষা ও গ্রন্থাগার

আপনি যে কোনও ভাষা বা লাইব্রেরি পছন্দ করতে পারেন।

মন্তব্য

ফাইলটিতে রেখার সংখ্যা গণনা করার বিষয়ে উদ্বেগ ছিল। নিমিতে মন্তব্যে উল্লেখ করার সাথে সাথে আপনি ফাইলের আকার এবং লাইন অনুসারে অক্ষরের সংখ্যা থেকে এটি নির্ধারণ করতে পারেন।

প্রেরণা

আড্ডায় কিছু লোক জিজ্ঞাসা করেছিল যে এটি সত্যই "ওয়াই ছাড়াই এক্স" প্রশ্ন কিনা। বিধিনিষেধগুলি অস্বাভাবিকভাবে কৃত্রিম কিনা তা জানতে আমি এটি ব্যাখ্যা করি।

বিশাল ফাইলগুলি থেকে এলোমেলোভাবে নমুনা রেখার কাজটি অস্বাভাবিক নয় এবং বাস্তবে এটি আমাকে কখনও কখনও করতে হয়। এটি করার একটি উপায় হ'ল বাশ:

shuf -n <num-lines>

এটি যদিও পুরো ফাইলটিতে পড়ে এটি বড় ফাইলগুলির জন্য খুব ধীর।


ডাউনটা কেন?

3
এটি সি এর মতো ভাষায় তুচ্ছ fseekএবং অন্যের পক্ষে অসম্ভব। অতিরিক্তভাবে, যদি nফাইলের লাইনের সংখ্যার চেয়ে বেশি হয় তবে কী হবে?
মেগো

4
@ মেগো: আপনার পয়েন্টটি সম্পর্কিত)) আপনি একটি লাইনের দৈর্ঘ্য দ্বারা ফাইলের আকার ভাগ করে লাইন সংখ্যা গণনা করতে পারেন।
নিমি

8
Y ছাড়াই ডো এক্স হ'ল সতর্কতা যা "এটি সর্বদা খারাপ হয় না" দিয়ে শুরু হয়। প্রধান সমস্যা যা ভাষায় যা আছে সুবিধা দেয় "+ ব্যবহার করবেন না" মত কৃত্রিম সীমাবদ্ধতা হল sum()। মেমোরিতে কোনও ফাইল না পড়া একটি স্পষ্ট এবং ধারাবাহিক সীমাবদ্ধতা যা কোনওভাবেই স্বেচ্ছায় নয়। এটি মেমরির চেয়ে বড় ফাইলের সাথে পরীক্ষা করা যেতে পারে, যা ভাষার পার্থক্য অনুসারে কাজ করা যায় না। বাস্তব বিশ্বের অ্যাপ্লিকেশনগুলিও ঘটে (যদিও এটি কোনও গল্ফের জন্য প্রয়োজনীয় নয় ...)।
ট্রাইকোপ্লেক্স

1
দেখে মনে হচ্ছে এটি আসলে একটি সীমাবদ্ধ জটিলতা কোড গল্ফ যেখানে সম্ভাব্য বিশাল ফাইল সত্ত্বেও মেমরির ব্যবহার সীমিত। এটি আপনার কোডে কিছু নির্দিষ্ট জিনিস না থাকার বিষয়ে নয় তবে কোড কীভাবে কাজ করতে পারে তার একটি সীমাবদ্ধতা।
xnor

উত্তর:


5

ডায়ালগ এপিএল , 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 বাইট পড়ুন 8-বিট সংখ্যার হিসাবে ফাইল -1 এর রূপান্তর কোড (83 রূপান্তর কোড)
10⍳⍨প্রথম সংখ্যা 10 (এলএফ) এর সূচকটি সন্ধান
l←করুন লাইন দৈর্ঘ্যের l
(⎕NSIZE t)÷সাথে ফাইলের আকার -1 ভাগ করুন
অঙ্কিত ইনপুট জন্য প্রম্পট (রেখার পছন্দসই সংখ্যা) )
?এক্স র্যান্ডম নির্বাচন (প্রতিস্থাপন ছাড়াই) প্রথম Y প্রাকৃতিক সংখ্যা বের করে out
¯1+ 0-উত্সের লাইন সংখ্যাগুলি পেতে -1 যোগ করুন *
শুরু বাইট পেতে রেখা দৈর্ঘ্য দ্বারা গুণ করুন প্রতিটি শুরুর বাইটে
t 82l∘,¨প্রিপেনড [-1,82, লাইনলাইন্থ] জন্য আর্গুমেন্টের তালিকা ⎕NREAD)
⎕NREAD¨ প্রতিটি লাইন 8-বিট অক্ষর হিসাবে পড়ুন (রূপান্তর কোড 82)

ব্যবহারিক উদাহরণ

ফাইল /tmp/records.txt এ রয়েছে:

Hello
Think
12345
Klaus
Nilad

প্রোগ্রামটি র্যান্ডলাইনগুলি এপিএল সেশনে নিম্নলিখিতটি প্রবেশ করে উপরের কোডটি ভারব্যাটিম ধারণ করুন:

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

এপিএল সেশনে টাইপ করুন RandLinesএবং এন্টার টিপুন।

সিস্টেমটি কার্সারটিকে পরবর্তী লাইনে নিয়ে যায়, যা অক্ষরের ডেটার জন্য 0-দৈর্ঘ্যের প্রম্পট; প্রবেশ /tmp/records.txt

সিস্টেম এখন আউটপুট ⎕:এবং সংখ্যার ইনপুট অপেক্ষা করে; প্রবেশ 4

সিস্টেমটি চারটি এলোমেলো লাইন আউটপুট করে।

বাস্তব জীবন

বাস্তবে, আপনি ফাইলের নাম দিতে এবং আর্গুমেন্ট হিসাবে গণনা করতে এবং ফলাফলটি একটি টেবিল হিসাবে পেতে চাইতে পারেন। প্রবেশ করে এটি করা যেতে পারে:

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

এখন আপনি মাইলাইনগুলিতে তিনটি এলোমেলো লাইন ধারণ করে:

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


আহ .. এপিএল :) লিনাক্সে এই কোডটি পরীক্ষা করার কোনও উপায় আছে?

@ ল্যাম্বিক শিওর, এই কোডটি ক্রস প্ল্যাটফর্ম। ডায়ালগ
ডট

আমি যেমন এপিএল পড়ি না, আপনি কোডটি ব্যাখ্যা করতে পারবেন? ছদ্মবেশী অংশগুলি প্রতিস্থাপন ছাড়াই লাইন নমুনা দিচ্ছে এবং লাইনগুলি পড়ার জন্য সরাসরি ফাইলের সঠিক জায়গায় লাফিয়ে চলেছে।

এই অংশটি সহজ! RENREAD এর যুক্তিটি টাইবার্বার কনভার্সনকোড বাইটসটোরইড [স্টার্টবাইট]। এটি কেবল প্রয়োজনীয় বাইটগুলি পড়ে। বাকীগুলি শুধু কী পড়বেন তা নির্ধারণ করছেন।
অ্যাডম

@ ল্যাম্বিক আমি আগ্রহী যে আমার উত্তর কেন অনুগ্রহ করে না win
অ্যাডম

7

রুবি, 104 94 92 90 বাইট

ফাইলের নাম এবং রেখার সংখ্যা কমান্ড লাইনে প্রেরণ করা হয়। উদাহরণস্বরূপ, প্রোগ্রামটি যদি shuffle.rbএবং ফাইলটির নাম হয় তবে তিনটি এলোমেলো লাইনের জন্য a.txtচালান ruby shuffle.rb a.txt 3

এর openপরিবর্তে রুবিতে সিনট্যাক্স আবিষ্কার করা থেকে 4 বাইট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
@ পিটারকর্ডস এটি উপলব্ধি করে, তবে যেমনটি উল্লেখ করা হয়েছে যে ব্যর্থতার বিষয়টি হ'ল রুবি স্টিডিনের ফাইলের আকারটি পড়তে পারছেন না, তাই এটি কার্যকর হয়নি।
মূল্য কালি

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 ফাংশনটির ।

সম্পাদনা: আমি "প্রতিস্থাপন ছাড়াই এলোমেলো" অংশটি মিস করেছি (ধন্যবাদ লক্ষ করার জন্য ধন্যবাদ!)।


হাস্কেল শিলা :)

1
এটি ইতিমধ্যে নির্বাচিত একটি লাইন বাছাই কীভাবে এড়ানো যায়?
feersum

@ ফেয়ারসাম: ওহ, আমি সেই অংশটি মিস করেছি। সংশোধন করা হয়েছে।
নিমি

আমি দেখতে পাচ্ছি স্ট্যাকওভারফ্লো.com/ প্রশ্নগুলি / 13779630/ … কিছুটা ভারবস!

1
অল্প জায়গায় প্রতিস্থাপন না করে নমুনা নেওয়ার ক্ষেত্রে পৃথক চ্যালেঞ্জ থাকতে পারে।

3

পাওয়ারশেল ভি 2 +, 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অবশ্যই একটি পূর্ণ-পথের ফাইল নাম হতে হবে এবং এটি এএনএসআই এনকোডিং হিসাবে ধরে নেওয়া হবে।

তারপরে আমরা একটি নতুন FileStreamঅবজেক্ট তৈরি করি এবং এটি সুবিধা $aসহ ফাইল অ্যাক্সেস করতে বলি Open

forলুপ .Read()যতক্ষণ না আমরা একটি আঘাত প্রথম লাইন s থেকে \nঅক্ষর, আমাদের লাইন দৈর্ঘ্যের পাল্টা প্রতিটি অক্ষর বৃদ্ধিশীল। তারপরে আমরা $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 থেকে ভারীভাবে চুরি হয়েছে তবে এটি অজগর 3.5 মাত্র এবং এটি একটি সম্পূর্ণ প্রোগ্রাম।

সম্পাদনা: ইনলাইন সীমা এবং পাইথন 3.x সামঞ্জস্যের জন্য @ মেগোকে ধন্যবাদ। সম্পাদনা 2: মুদ্রণটি কোথায় তা সম্পর্কে স্পষ্টতা কারণ আমি এটি সম্পর্কে দুটি মন্তব্য পেয়েছি। (মন্তব্য স্পষ্টতই কোড বা বাইট গণনার অংশ নয়))


ধন্যবাদ! অজগর 3.5 অংশ কোন অংশ?

2
r=range(f.seek(0,2)//l)কাজ করবে, যা 3 বাইট বন্ধ করে দেয় এবং 3.5 এর প্রয়োজনীয়তা সরিয়ে দেয়। আরও ভাল, rangeকলটিতে ইনলাইন করে আরও 3 টি বাইট শেভ sampleকরুন। অতিরিক্তভাবে, এটি একটি সম্পূর্ণ প্রোগ্রাম নয় - আপনাকে আসলে তালিকাটি মুদ্রণ করতে হবে।
মেগো

@ লেলেবিক: এটি কেবলমাত্র 3.5 ব্যবহারের r=[*range(f.seek(0,2)//l)]কারণে আমি ভেবেছিলাম যে আমি sampleজেনারেটর করতে পারব না couldn't আমি পেরেছি। @ মেগা: এটি সম্পূর্ণ কারণ এটি তালিকা বোঝার ভিতরে প্রতিটি লাইন প্রিন্ট করে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 হিসাবে রয়েছে কারণ আমার পরীক্ষার ফাইলটি এটি ছিল।

নিজেকে পিএইচপি প্রবেশের অধীনে পেয়েছি তবে এখনও দ্বিতীয় স্থান (বর্তমানে)। অভিশাপ, রুবি প্রবেশ!


1
লুয়া হ'ল আমি প্রথম প্রোগ্রামিং ল্যাঙ্গুয়েজ শিখেছি এবং এমনকি তখন থেকে আমি যা শিখেছি তা এখনও আমার প্রিয়। এটি সহজেই লেখার পক্ষে বহুমুখী।
ব্লেব 12:58

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=noneআউট স্ট্রিপ প্রয়োজন হয় তথ্য সাধারণত আউটপুটdd

আমরা ব্যবহার করে লাইনের দৈর্ঘ্য 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 টিপ দেওয়ার জন্য ধন্যবাদ !


1
আমি সবসময় ব্যাশের উত্তর পছন্দ করি তবে আপনি কী ব্যাখ্যা করতে পারবেন যে এটি কীভাবে পুরো ফাইলটি পড়ে না?

2
@ ল্যাম্বিক যোগ করেছেন ব্যাখ্যা!
ডম হেস্টিংস

1
আপনি bs=পরিবর্তে করতে পারেন ibs=, যেহেতু সেটিংসও obsঠিক আছে। আমার ধারণা আপনি যদিও এর if=$2সাথে প্রতিস্থাপন করতে পারবেন না <$2, কারণ এটি এখনও xargsকমান্ড লাইন। \<$2হয় কাজ করে না (xargs সরাসরি শেল ছাড়াই এক্সিকিউট ব্যবহার করে)।
পিটার কর্ডেস

আমি আশা করি এটি খুব বেশি নয় তবে আমি এই উত্তরটিকে পছন্দ করি :) কেবল এটি একটি 1 জিবি ফাইলের সাথে পরীক্ষা করেছে।

1
পুনরায়: স্ট্ডারকে স্টিডিনে পুনর্নির্দেশ: আপনি স্ট্ডারটি বন্ধ করেও 2>&-দেখতে পারেন, ফলে আউটপুট কোথাও যাওয়ার কোনও আশঙ্কা নেই (যেমন স্টিডিন যদি রিড-রাইটিং ফাইল বর্ণনাকারী হয়ে থাকে)। এটি জিএনইউতে কাজ করে 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
চ্যালেঞ্জটির জন্য একটি পূর্ণ প্রোগ্রাম প্রয়োজন, তাই আমি ভয় করি যে কোনও ফাংশন সংজ্ঞা যথেষ্ট নয়।
নিমি

আমদানি এবং * এর মধ্যে বাইট অপসারণের স্থানটি সংরক্ষণ করতে।
mriklojn

1
@ নিমিমি এই চ্যালেঞ্জটির জন্য একটি পূর্ণ প্রোগ্রামের প্রয়োজন বলে মনে হচ্ছে নির্বিচারে ডিফল্ট কোড ফর্ম্যাট নিয়মগুলিকে ওভাররাইড করছে
পিপ্রি

@ পিপ্পেরি: হ্যাঁ, সম্ভবত, তবে এটি ঠিক এটিই।
নিমি

ফাইলটির দৈর্ঘ্য পেতে আপনি f.seek করতে পারেন (0,2) , এটি আমদানি করে ওএস এবং os.stat অপ্রচলিত।
আলেকজান্ডার নিগল

1

নকল ছাড়াই সি # 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());
    }
}

ফাইল.আরেডলাইনস অলস। এর অতিরিক্ত সুবিধা রয়েছে যা সমস্ত লাইনের আলাদা দৈর্ঘ্য থাকতে পারে।

এটি চালানো হবে:

sample.exe a.txt 10000

ডুপ্লিকেট সহ সি # 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());
    }
}

আমি আপনার সমাধানটি পুরোপুরি অনুসরণ করি না। যদি সমস্ত লাইনের দৈর্ঘ্য আলাদা হয় তবে কাজটি অসম্ভব। এছাড়াও, আপনি ঠিক কিভাবে প্রতিস্থাপন ছাড়াই এলোমেলোভাবে নমুনা লাইন করছেন ? আমি ক্ষমা চাইছি আমার সি # যথেষ্ট ভাল নয়।

@ ল্যাম্বিক আপনি ঠিক বলেছেন, আমি সদৃশ সম্পর্কে ভাবিনি। এবং আমি লিনেনম্বার দ্বারা লাইনগুলির সংখ্যা এবং লাইনগুলি বের করতে পারি, এ কারণেই লাইনগুলি পরিবর্তনশীল দৈর্ঘ্য হতে পারে।
117

তবে আপনাকে কেবল লাইন নম্বরটি জেনে ফাইলের কোনও অবস্থানে যেতে হবে? সমস্ত লাইন একই দৈর্ঘ্য না থাকলে আপনি তা বলতে পারবেন না।

@ লেলেবিক ফাইল.আরডলাইনস ("প্যাথটোফাইল") ফাইলের সমস্ত লাইনগুলিতে একটি অলস গণনা তৈরি করে, ফাইল.আরডলাইনস ("প্যাথটোফাইল")। এলিমেন্টএট (19) ফাইলের 19 তম লাইনে ফিরে আসে। কিন্ডা সমস্ত লাইনস্টার্টের মানচিত্রের মতো।
117

আমি মনে করি না যে অলস গণনাটি দুঃখজনকভাবে ফাইলটিতে লাফিয়ে উঠেছে (বা সন্ধান করে)। সুতরাং এটি বর্তমানে নিয়মগুলির সাথে খাপ খায় না।

1

পাইথন (141 বাইট)

প্রতিটি লাইন সমান সম্ভাব্যতার সাথে রাখে, পাইপগুলির সাথেও ব্যবহার করুন। এটি প্রশ্নের সীমাবদ্ধতার সামনে এড়াতে উত্তর দেয় না যদিও ...

ব্যবহার cat largefile | python randxlines.py 100বা python randxlines 100 < largefile(যেমন @ পেটারকর্ডস নির্দেশ করেছেন)

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সেক্ষেত্রে অনুসন্ধানযোগ্য হবে।
পিটার কর্ডেস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.