잠재적으로 큰 파일에서 n 개의 임의 행을 읽습니다.


16

이 과제는 전체 파일을 메모리로 읽지 않고 잠재적으로 큰 파일에서 임의의 행을 읽는 것입니다.

입력

n텍스트 파일 의 정수 및 이름입니다.

산출

n 대체하지 않고 무작위로 균일하게 선택된 텍스트 파일의 행.

n파일의 1-행 수 범위에 있다고 가정 할 수 있습니다 .

n당신이 얻는 대답이 균일 한 범위에서 무작위로 숫자를 샘플링 할 때주의하십시오 . rand()%n예를 들어 C에서 균일하지 않다. 모든 결과는 똑같이 가능해야합니다.

규칙과 제한

텍스트 파일의 각 줄은 같은 문자 수를 가지며 80자를 넘지 않습니다.

코드는 다음을 제외하고 텍스트 파일의 내용을 읽지 않아야합니다.

  • 그 라인이 출력합니다.
  • 텍스트 파일에 한 줄에 몇 개의 문자가 있는지 알아내는 첫 번째 행.

텍스트 파일의 각 문자는 정확히 1 바이트를 사용한다고 가정 할 수 있습니다.

줄 구분자는 1 바이트 길이 인 것으로 가정합니다. 솔루션은 이러한 요구를 지정하는 경우에만 2 바이트 길이의 줄 구분 기호를 사용할 수 있습니다. 마지막 줄이 줄 구분자로 끝나는 것으로 가정 할 수도 있습니다.

답변은 완전한 프로그램이어야하지만 편리한 방법으로 입력을 지정할 수 있습니다.

언어와 라이브러리

원하는 언어 나 라이브러리를 사용할 수 있습니다.

노트

파일의 줄 수를 계산하는 데 문제가있었습니다. nimi가 주석에서 지적한 것처럼 파일 크기와 줄 당 문자 수에서 이것을 추론 할 수 있습니다.

자극

채팅에서 일부 사람들은 이것이 "Y없이 X로"질문인지 물었습니다. 나는 제한이 비정상적으로 인공적인지를 묻기 위해 이것을 해석합니다.

거대한 파일에서 무작위로 라인을 샘플링하는 작업은 드문 일이 아니며 실제로 내가해야 할 일입니다. 이를 수행하는 한 가지 방법은 bash입니다.

shuf -n <num-lines>

그러나 전체 파일을 읽을 때 큰 파일의 경우 속도가 매우 느립니다.


왜 공감해야합니까?

3
이것은 C와 같은 언어에서는 사소하고 다른 언어 fseek에서는 불가능합니다. 또한 n파일의 줄 수보다 크면 어떻게됩니까?
메고

4
@Mego : 포인트 관련 b) : 파일 크기를 줄 길이로 나누어 줄 수를 계산할 수 있습니다.
니미

8
Y없는 X 는 "항상 나쁘지는 않습니다"로 시작하는 경고입니다. 주요 문제는 "사용하지 않는 +"와 같은 인공적인 제한 사항이있는 언어를 사용하는 것 sum()입니다. 파일을 메모리로 읽지 않는 것은 명확하고 일관된 제한 사항이며, 이는 결코 임의적이지 않습니다. 언어 차이로 해결할 수없는 메모리보다 큰 파일로 테스트 할 수 있습니다. 또한 실제 응용 프로그램이 있습니다 (골프에는 필요하지 않지만 ...).
trichoplax

1
이것은 실제로 거대한 파일에도 불구하고 메모리 사용량이 제한되는 제한된 복잡성 코드 골프처럼 보입니다. 코드에 특정 사항이없는 것이 아니라 코드의 작동 방식에 대한 제한입니다.
xnor

답변:


5

Dyalog APL , 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 (LF)
l←행 길이를 l
(⎕NSIZE t)÷파일 형식 으로 나누기 행 길이로 나누기
숫자 입력 프롬프트 (원하는 행 수) )
?첫 Y 자연수에서 X 임의 선택 (교체없이)
¯1+-1을 추가하여 0- 원점 라인 번호
를 얻습니다. * 줄 길이를 곱하여 시작 바이트를 얻습니다.
t 82l∘,¨ 앞에 [-1,82, LineLength]를 추가합니다 의 인수 목록 ⎕NREAD)
⎕NREAD¨ 각 줄을 8 비트 문자로 읽습니다 (변환 코드 82).

실제 예

/tmp/records.txt 파일에는 다음이 포함됩니다.

Hello
Think
12345
Klaus
Nilad

APL 세션에 다음을 입력하여 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.

시스템은 4 개의 임의 라인을 출력합니다.

현실

실제로 파일 이름을 지정하고 인수로 계산하고 결과를 테이블로받을 수 있습니다. 다음을 입력하여 수행 할 수 있습니다.

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

이제 MyLines에 다음과 같은 임의의 세 줄이 포함됩니다.

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

count가 지정되지 않은 경우 단일 임의의 줄만 반환하는 방법은 다음과 같습니다.

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'

코드를 읽을 수있게 만들기

골프 APL 원 라이너는 나쁜 생각입니다. 프로덕션 시스템에서 작성하는 방법은 다음과 같습니다.

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
}

* 일부 APL 시스템에서 표준 인 0- 원점 모드에서 실행하여 바이트를 절약 할 수 있습니다 : remove ¯1+and insert 1+before 10.


Ahh .. APL :) 리눅스에서이 코드를 테스트하는 방법이 있습니까?

@Lembik 물론,이 코드는 크로스 플랫폼입니다. dyalog.com에서 다운로드
Adám

APL을 읽지 않아도 코드를 설명 할 수 있습니까? 까다로운 부분은 교체 없이 라인 샘플링 하고 파일의 올바른 위치로 직접 점프하여 라인을 읽습니다.

@Lembik 그 부분은 쉽습니다. READNREAD의 인수는 TieNumber ConversionCode BytesToRead [StartByte]입니다. 필요한 바이트 만 읽습니다. 나머지는 읽을 내용을 파악하고 있습니다.
Adám

@Lembik 나는 왜 내 대답이 현상금을 얻지 못했는지 궁금합니다.
Adám

7

루비, 104 94 92 90 바이트

파일 이름과 줄 수는 명령 줄에 전달됩니다. 예를 들어, 프로그램이 shuffle.rb있고 파일 이름이 a.txt인 경우 ruby shuffle.rb a.txt 3임의의 3 행에 대해 실행하십시오 .

openRuby 에서 구문 을 발견 하지 않고 -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 반복을 피합니다. 말하지 마 ... 내가 반복해야 했습니까?
Value Ink

당신은 완벽하지 않습니다 :)

stdin에서 읽음으로써 바이트를 저장할 수 있습니까? ruby shuffle.rb 3 < a.txt당신에게 찾기 쉬운 stdin을 제공합니다. IDK 루비.
Peter Cordes

1
@PeterCordes 그건 말이 되겠지만, 언급 한 바와 같이 루비는 stdin의 파일 크기를 읽을 수 없기 때문에 문제가 해결되지 않았습니다.
가치 잉크

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

stdin에서 파일 이름과 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기능으로 인해 많은 행을 가진 파일에 대해이 프로그램을 실행하려면 많은 시간과 메모리가 필요합니다 .

편집 : 나는 "교체없이 무작위"부분을보고 싶었습니다 (@feersum 감사합니다!).


하스켈 바위 :)

1
이미 선택된 라인을 선택하지 않으려면 어떻게해야합니까?
feersum

@ feersum : 아, 나는 그 부분을 놓쳤다. 결정된.
nimi


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객체 를 생성 하고 파일 $aOpen권한 으로 액세스하도록 지시합니다 .

for루프는 .Read()우리가 공격 할 때까지 첫 번째 라인을 통해 s의 \n우리의 선 길이 카운터 각 문자를 증가, 문자. 그런 다음 $t파일 크기 (즉, 스트림 길이)를 줄당 문자 수 (더하기 1을 더해서 종료 문자 수)로 나눈 값 (제로 인덱스이므로 0)으로 설정합니다. 그런 다음 버퍼 $z를 줄 길이로 만듭니다.

마지막 줄은 ..range 연산자를 사용하여 동적 배열을 구성합니다 . 1 우리 파이프 것과 어레이 Get-RandomA의 -C의 ount $n무작위 선택에 $n반복없이 행 번호. 행운의 숫자는와 함께 루프에 파이프됩니다 |%{...}. 각각의 반복 .Seek은 특정 위치로, 그리고 한 .Read줄에 해당하는 문자로 저장됩니다 $z. 우리 $z는 char-array로 다시 캐스트 -join하고 결과 문자열을 파이프 라인에 남겨두고 출력은 프로그램 끝에서 암시 적입니다.

기술적으로 우리는 $f.Close()파일을 닫으 라는 호출로 끝내야 하지만 그 비용은 바이트입니다! :피

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

@Lembik : 발전기를 r=[*range(f.seek(0,2)//l)]사용할 수 없다고 생각했기 때문에 사용 했기 때문에 3.5였습니다 sample. 내가 할 수있는 것으로 밝혀졌습니다. @Mega :리스트 이해의 모든 줄을 인쇄하기 때문에 완성되었습니다print(f.read(l))
Alexander Nigl

그래도 인쇄 문이 필요합니다.

인쇄는 목록 이해 안에 있습니다.
Alexander Nigl

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이기 때문에 2 만 있습니다.

PHP 항목 아래에 있지만 여전히 2 위 (현재)입니다. 저주, 루비 엔트리!


1
루아는 내가 처음 배운 프로그래밍 언어였으며, 그 이후로 배운 모든 언어를 사용하더라도 여전히 가장 좋아하는 언어입니다. 쓰기가 쉬워 다재다능합니다.
Blab

2

배쉬 (well, coreutils), 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과 같습니다 * 바이트 를 반환합니다) 반환 할 길이 섹션 의 수는 스트립 아웃해야합니다 에 의해 정상적으로 출력되는 정보ibsskipibs
countibs
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

vs.

time shuf -n4 test.txt
1204350
3496441
3472713
3985479

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

를 사용하여 생성 된 68MiB 파일에 대한 시간 seq 1000000 9999999 > test.txt입니다.

그의 팁에 대한 @PeterCordes 에게 감사합니다 !


1
나는 항상 bash 답변을 좋아하지만 이것이 전체 파일을 읽지 않는 방법을 설명 할 수 있습니까?

2
@Lembik은 설명을 추가했습니다!
Dom Hastings

1
설정 도 괜찮 기 때문에 bs=대신 대신 사용할 수 있습니다 . 나는 당신이 대체 할 수 생각 으로 이 여전히 있기 때문에, 비록 의 명령 행. 작동하지 않습니다 (xargs는 쉘없이 exec를 직접 사용합니다). ibs=obsif=$2<$2xargs\<$2
Peter Cordes

나는 이것이 너무 많지 않기를 희망하지만 나는이 답변을 좋아한다. :) 1GB 파일로 테스트했다.

1
다시 : stderr을 stdin으로 리디렉션 :으로 stderr을 닫을 수 2>&-있으므로 출력이 어디든지 갈 위험이 없습니다 (예 : stdin이 읽기-쓰기 파일 설명자가 된 경우). GNU와 함께 작동 합니다 . 쓰기를 시도하고 실패하기 전에 dd여전히 생성 stdout합니다 stderr.
Peter Cordes

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

바이트를 저장하려면 import와 * 사이의 공백을 제거하십시오.
mriklojn

1
이 문제에 대한 전체 프로그램을 요구하는 @nimi가 될 것으로 보인다 arbitarily 기본 코드 형식의 규칙을 무시
pppery

@ ppperry : 예, 어쩌면 그랬습니다.
nimi

파일의 길이를 얻으려면 f.seek (0,2) 할 수 있으므로 import os 및 os.stat는 더 이상 사용되지 않습니다.
Alexander Nigl

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());}}

언 골프

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());}}

언 골프

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());
    }
}

나는 당신의 해결책을 완전히 따르지 않습니다. 모든 줄의 길이가 다르면 작업이 불가능합니다. 또한 정확히 교체 하지 않고 무작위로 라인 샘플링하는 방법은 무엇입니까? C #이 충분하지 않아서 죄송합니다.

@Lembik 당신이 옳습니다, 나는 중복에 대해 생각하지 않았습니다. 그리고 줄 수를 계산하고 줄 번호로 줄을 추출 할 수 있으므로 줄이 가변 길이 일 수 있습니다.
Master117

그러나 줄 번호 만 아는 파일의 위치로 이동해야합니까? 모든 줄의 길이가 같지 않으면 그 위치를 알 수 없습니다.

@Lembik File.ReadLines ( "pathToFile")은 File의 모든 행에 Lazy 열거를 생성합니다. File.ReadLines ( "pathToFile"). elementAt (19)는 파일의 19 번째 행을 반환합니다. 모든 라인 스타트의지도를 좋아하십시오.
Master117

Lazy 열거 형이 파일에서 슬프게 점프한다고 생각하지 않습니다. 따라서 현재 규칙에 맞지 않습니다.

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
이 질문의 핵심은 입력 스트림을 찾아야한다는 것입니다. 당신은 아마 말할해야 그건 당신이 무시하고있는 문제의 제한의 일부 (읽기에서-A-파이프 예를 들어, 사용 차종하지만 꽤 분명 그). stdin에서 읽는 python ./randxlines.py 100 < largefile것은 정답 을 얻는 데 좋을 것 stdin입니다.
Peter Cordes
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.