Microsoft PowerPoint - lua_script11_18.ppt



Similar documents
03_queue

슬라이드 1

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

Chapter 4. LISTS

5.스택(강의자료).key

03장.스택.key

Microsoft PowerPoint - 08-chap06-Queue.ppt

예제 1.1 ( 관계연산자 ) >> A=1:9, B=9-A A = B = >> tf = A>4 % 4 보다큰 A 의원소들을찾을경우 tf = >> tf = (A==B) % A

Chap 6: Graphs

chap01_time_complexity.key

Microsoft Word - FunctionCall

슬라이드 1

Contents v 학습목표 자료구조큐에대한개념을스택과비교하여이해한다. 큐의특징과연산방법에대해알아본다. 순차표현방법을이용한큐와연결표현방법을이용한큐를구현해본다. 큐의응용방법을알아본다. v 내용 큐 큐의구현 큐의응용 2/74

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

Microsoft PowerPoint - 08-Queue.ppt

chap 5: Trees

설계란 무엇인가?

Microsoft PowerPoint - chap10-함수의활용.pptx

Microsoft PowerPoint - ch07 - 포인터 pm0415

Data structure: Assignment 1 Seung-Hoon Na October 1, Assignment 1 Binary search 주어진 정렬된 입력 파일이 있다고 가정하자. 단, 파일내의 숫자는 공백으로 구 분, file내에 숫자들은

A Hierarchical Approach to Interactive Motion Editing for Human-like Figures

04장.큐

컴파일러

C++ Programming

PowerPoint 프레젠테이션

설계란 무엇인가?

종사연구자료-이야기방 hwp

인천광역시의회 의원 상해 등 보상금 지급에 관한 조례 일부개정조례안 의안 번호 179 제안연월일 : 제 안 자 :조례정비특별위원회위원장 제안이유 공무상재해인정기준 (총무처훈령 제153호)이 공무원연금법 시행규칙 (행정자치부령 제89호)으로 흡수 전면 개

목 차 국회 1 월 중 제 개정 법령 대통령령 7 건 ( 제정 -, 개정 7, 폐지 -) 1. 댐건설 및 주변지역지원 등에 관한 법률 시행령 일부개정 1 2. 지방공무원 수당 등에 관한 규정 일부개정 1 3. 경력단절여성등의 경제활동 촉진법 시행령 일부개정 2 4. 대

A Dynamic Grid Services Deployment Mechanism for On-Demand Resource Provisioning

슬라이드 1

o 스택 (stack) ~ 쌓아놓은더미 1. 스택의개요 - 2 -

목차 포인터의개요 배열과포인터 포인터의구조 실무응용예제 C 2

MySQL-.. 1

untitled

Microsoft PowerPoint - chap05-제어문.pptx

USER GUIDE

PowerPoint Presentation

Chapter 4. LISTS

8장 문자열

<342EBAAFBCF620B9D720B9D9C0CEB5F92E687770>

Microsoft PowerPoint 자바-기본문법(Ch2).pptx

Tcl의 문법

제 14 장포인터활용 유준범 (JUNBEOM YOO) Ver 본강의자료는생능출판사의 PPT 강의자료 를기반으로제작되었습니다.

Microsoft PowerPoint - C++ 5 .pptx

Microsoft PowerPoint - logo_3.ppt [호환 모드]

Chapter 4. LISTS

PowerPoint 프레젠테이션

11장 포인터

Microsoft PowerPoint - chap04-연산자.pptx

1 경영학을 위한 수학 Final Exam 2015/12/12(토) 13:00-15:00 풀이과정을 모두 명시하시오. 정리를 사용할 경우 명시하시오. 1. (각 6점) 다음 적분을 구하시오 Z 1 4 Z 1 (x + 1) dx (a) 1 (x 1)4 dx 1 Solut

강의 개요

02장.배열과 클래스

학습목표 함수프로시저, 서브프로시저의의미를안다. 매개변수전달방식을학습한다. 함수를이용한프로그래밍한다. 2

Week5

Microsoft PowerPoint - chap03-변수와데이터형.pptx

adfasdfasfdasfasfadf

5장. JSP와 Servlet 프로그래밍을 위한 기본 문법(완성-0421).hwp

Javascript.pages

<322EBCF8C8AF28BFACBDC0B9AEC1A6292E687770>

그 여자와 그 남자의 사랑 이야기

API 매뉴얼

PowerPoint 프레젠테이션

06장.리스트

OCaml

Microsoft PowerPoint - chap13-입출력라이브러리.pptx

삼외구사( 三 畏 九 思 ) 1981년 12월 28일 마산 상덕법단 마산백양진도학생회 회장 김무성 외 29명이 서울 중앙총본부를 방문하였을 때 내려주신 곤수곡인 스승님의 법어 내용입니다. 과거 성인께서 말씀하시길 道 를 가지고 있는 사람과 어울려야만 道 를 배울 수 있

Microsoft PowerPoint - 3ÀÏ°_º¯¼ö¿Í »ó¼ö.ppt

기사스크랩 (160504).hwp

학습목차 2.1 다차원배열이란 차원배열의주소와값의참조

chap x: G입력

Columns 8 through while expression {commands} 예제 1.2 (While 반복문의이용 ) >> num=0

35.PDF

Microsoft PowerPoint - a10.ppt [호환 모드]

Microsoft PowerPoint 웹 연동 기술.pptx

산림병해충 방제규정 4. 신문 방송의 보도내용 등 제6 조( 조사지역) 제5 조에 따른 발생조사는 다음 각 호의 지역으로 구분하여 조사한다. 1. 특정지역 : 명승지 유적지 관광지 공원 유원지 및 고속국도 일반국도 철로변 등 경관보호구역 2. 주요지역 : 병해충별 선단

Microsoft PowerPoint - hw8.ppt [호환 모드]

Algorithms

김기중 - 방송통신심의위원회 인터넷 내용심의의 위헌 여부.hwp

UI TASK & KEY EVENT

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202839C1D6C2F7207E203135C1D6C2F >


PowerPoint 프레젠테이션

슬라이드 1

Microsoft PowerPoint - 07-chap05-Stack.ppt

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C4C656D70656C2D5A69762E637070>

Microsoft PowerPoint - chap11-포인터의활용.pptx

Microsoft PowerPoint - ch08_큐 [호환 모드]

15강 판소리계 소설 심청전 다음 글을 읽고 물음에 답하시오. [1106월 평가원] 1)심청이 수궁에 머물 적에 옥황상제의 명이니 거행이 오죽 하랴. 2) 사해 용왕이 다 각기 시녀를 보내어 아침저녁으로 문 안하고, 번갈아 당번을 서서 문안하고 호위하며, 금수능라 비

중등2단계(최종)-PDF용.hwp

PowerPoint Presentation

Microsoft PowerPoint - 제11장 포인터(강의)

KNK_C_05_Pointers_Arrays_structures_summary_v02

Microsoft PowerPoint - [2009] 02.pptx

2. QUEUE OPERATIONS Initialize the queue Insert to the rear of the queue (also called as Enqueue) Remove (Delete) from the front of the queue (also ca

Microsoft PowerPoint - ch10 - 이진트리, AVL 트리, 트리 응용 pm0600

단위: 환경정책 형산강살리기 수중정화활동 지원 10,000,000원*90%<절감> 형산강살리기 환경정화 및 감시활동 5,000,000원*90%<절감> 9,000 4, 민간행사보조 9,000 10,000 1,000 자연보호기념식 및 백일장(사생,서예)대회 10


래를 북한에서 영화의 주제곡으로 사용했다든지, 남한의 반체제세력이 애창한다 든지 등등 여타의 이유를 들어 그 가요의 기념곡 지정을 반대한다는 것은 더 이상 용인될 수 없는 반민주적인 행동이 될 것이다. 동시에 그 노래가 두 가지 필요조 건을 충족시키지 못함에도 불구하고

비트와바이트 비트와바이트 비트 (Bit) : 2진수값하나 (0 또는 1) 를저장할수있는최소메모리공간 1비트 2비트 3비트... n비트 2^1 = 2개 2^2 = 4개 2^3 = 8개... 2^n 개 1 바이트는 8 비트 2 2

Transcription:

11 자료구조

11.1 1.1 배열 자료구조: 자료(사실 사실, 값) + 처리 방법 테이블: 루아의 유일한 자료구조. 전산학의 모든 자료구조를 처리할 수 있고, 효율적 배열: 순차 자료구조. 테이블로 가변적인 배열 표현 a = {} -- 새로운 배열 for i=1, 1000 do a[i] = 0 -- 길이 출력 print(table.getn(a)) print(#a) a = {} -- 새로운 배열 for i=1, 1000 do a[i] = 0 루아는 인덱스를 1부터시작 -- [-5, 5] 범위로 배열생성 a = {} for i=-5, 5 do a[i] = 0 print(table.getn(a)) --> 5 생성자를 사용 단일 수식으로 배열 초기화 squares = {1, 4, 9, 16, 25, 36, 49, 64, 81}

11.2 행렬과 다차원 배열 배열의 배열 mt = {} -- 테이블로 행렬 생성 for i=1,n do mt[i] = {} -- 새로운 열(column) 생성 for j=1,m do mt[i][j] ] = 0 -- 새로운 행(row) 생성 초기화 0 1차원 배열로 생성 mt = {} -- create the matrix for i=1,n do for j=1,m do mt[i*m + j] = 0 희소 행렬(sparse matrix): 행렬의 값이 거의 0으로 채워진 행렬 루아 테이블을 사용하면 nil로 검색하면서 처리 --> 매우 효율적 -- 두행렬의 곱. 값이 nil이면 곱셈을 처리하지 않음 function mult(a, rowindex, k) local row = a[rowindex] for i, v in pairs(row) do row[i] = v * k

11.3 연결 리스트 노드가 {자료 + 링크 포인터}를 가지고 한 줄로 연결되어 있는 방식으로 데이터를 저장하는 자료 구조 -- 리스트 정의 list = nil list ={ value = v, next = list} -- 리스트 순회 local l = list while l do print(l.value) l = l.next

11.4 스택(stack (stack), 큐 (Queue) Queue)와 덱(Deque (Deque: Doubly Queue) 큐: FIFO (First in First Out) 선입 선출 자료구조 동작: push back, pop front Deque(데크 데크): 이중 노드를 사용해서 큐와 스택을 합친 자료구조 동작: push front, pop front, push rear, pop rear

11.4 스택(stack (stack), 큐 (Queue) Queue)와 덱(Deque (Deque: Doubly Queue) 스택: LIFO(Last In First Out) 후입선출 자료구조 스택 위치를 기억하는 top이 존재 동작: push: 원소의 추가, pop : 원소 꺼내오기 -- 스택에대한 자료구조 function NewStack () return {top = 0} Stack={} function Stack.push(lst, value) -- 스택에 자료 추가(push) local top = lst.top + 1 -- top 위치 1증가 lst.top = top lst[top] = value function Stack.Dequeue (lst lst) -- 스택에서 원소 꺼내오기(pop) local top = lst.top -- top 위치 1 증가 if top<0 then print("stack Under Flow"); return local value = lst[top] lst[top] = nil -- 초기화 top = top -1 -- top 위치 1 감소 return value

11.4 스택(stack (stack), 큐 (Queue) Queue)와 덱(Deque (Deque: Doubly Queue) Queue: FIFO (First in First Out) 선입 선출 자료구조 자료의 위치를 기억하는 front, rear가 존재 동작: Enqueue: 원소를 rear에 추가, Dequeue: 원소를 front에서 꺼내오기 function NewQueue () -- 큐에대한 자료구조 return {front = 0, rear = 0} Queue ={} function Queue.Enqueue (lst lst, value) -- 큐의 rear에 insert (Enqueue ( Enqueue) local rear = lst.rear + 1 -- rear 위치 1증가 lst.rear = rear lst[rear] = value function Queue.Dequeue (lst lst) -- 큐의 front에서 원소 꺼내오기 (Dequeue Dequeue) local front = lst.front if front >= lst.rear then -- front 위치가 rear보다 같거나 크면 큐가 비어있는 것 error("lst is empty") local value = lst[front] lst[front] = nil -- 초기화 lst.front = front + 1 -- front 위치 1증가 return value

11.4 스택(stack (stack), 큐 (Queue) Queue)와 덱(Deque (Deque: Doubly Queue) 덱(Deque): 큐의 자료구조에 스택의 동작을 추가한 구조 자료의 위치를 기억하는 front, rear가 존재 동작: push_front- 원소를 front앞에 추가 push_back- 원소를 rear에 추가 pop_front- front 원소 꺼내오기 pop_back- rear 원소 꺼내오기 function DequeNew () --덱의 자료구조: 큐와 동일 return {front = 0, rear = 0} Deque = {} function Deque.push_front (lst lst, value) -- 덱의 front에 insert local front = lst.front - 1 -- front 위치를 1감소 시킴 lst.front = front lst[front] = value -- 감소된 front 위치에 원소 추가 -- 1 감소된

11.4 스택(stack (stack), 큐 (Queue) Queue)와 덱(Deque (Deque: Doubly Queue) function Deque.push_rear (lst lst, value) -- 덱의 rear에 insert local rear = lst.rear + 1 -- rear 위치를 1 증가 lst.rear = rear lst[rear] = value function Deque.pop_front (lst lst) -- 덱의 front에서 원소 꺼내오기 local front = lst.front if front >= lst.rear then error("lst is empty") local value = lst[front] lst[front] = nil -- 초기화 lst.front = front + 1 -- front 위치 1 증가 return value End function Deque.poprear (lst lst) -- 덱의 rear에서 원소 꺼내오기 local rear = lst.rear if lst.front >= rear then error("lst is empty") local value = lst[rear] lst[rear] = nil -- 초기화 lst.rear = rear - 1 -- rear 위치 1 감소 return value

11.5 집합과 멀티 셋 집합(set) 자료구조: 원소 자체가 자료를 구분하는 식별자로 구성된 자료구조, 원소의 중복은 없음. 멀티-셋: 원소의 중복이 허락된 셋 --루아의 예약어를 문자열 키(key) (key)로 사용하는 방법 reserved = { ["while"] = true, [""] = true, ["function"] = true, ["local"] = true, } for w in allwords() do if reserved[w] then -- `w' 처리 -- 좀 더 향상된 방법 function Set (lst lst) local set = {} for _, l in ipairs(lst) do set[l] = true return set reserved = Set{"while", ", "", "function", "local", }

11.5 집합과 멀티 셋 멀티 셋: 키마다 카운터를 설정, 중복된 원소 만큼 카운터 올림 --멀티 셋 원소 추가 function insert(bag, element) bag[element] = (bag[element bag[element] or 0) + 1 -- 멀티 셋 원소 감소 -- 카운터의 숫자가 1 보다 작으면 nil function remove(bag, element) local count = bag[element] bag[element] = (count and count > 1) and count -1 or nil

11.6 문자열 버퍼 루아의 문자열 변경은 불가. 파일에서 문자열을 읽을 때 새로운 문자열을 만들게 되므로 메모리가 증가될 수 있음 table.concat(): 주어진 리스트의 모든 문자열을 병합 -- 파일에 저장된 문자열을 하나의 큰 문자열로 합병 local t = {} for line in io.lines() do t[#t + 1] = line.. "\n" s = table.concat(t) -- 제일 작은 문자열 길이부터 큰 문자열 길이 순으로 합병 function addstring (stack, s) stack[#stack +1] = s for i=#stack-1, 1, -1 do if #stack[i+1] < #stack[i stack[i] then break stack[i] = stack[i].. statck[i+1] statck[i+1] = nil

11.7 그래프 (Graph) 도형으로 표현되는 비 선형 자료구조 연결할 객체를 나타내는 정점(Vertex), 이를 연결하는 간선 (Edge)의 집합으로 표현 -- 하나의 정점에 간선의 집합으로 표현 graph = {vertex, edge } -- 또는 정점(또는 노드)의 이름과 인접한 노드들의 집합으로 변경 graph = {name, adj} local function name2node(graph, name) if not graph[name] then -- 노드가 존재하지 않음. 새로운 노드 생성 graph[name] = { name = name, adj = adj{} } return graph[name]

11.7 그래프 (Graph) -- 파일로부터 그래프 읽기 function read_graph() local graph = {} for line in io.lines() do -- 이름 두 개로 줄을 분할 local namefrom, nameto = string.match(line, "(%S+)%s+(%S S+)%s+(%S+)" +)" ) -- 적당한 노드들을 찾는다. local from = name2node(graph, namefrom) local to = name2node(graph, nameto) -- 'from'에 인접한 집합에 'to' 를 더한다 from.adj[to] = true return graph "(% "(%S+)%s+(%S S+)%s+(%S+)" +)" --> 정규표현으로 %S+는 공백이 %s+ 공백문자가 1번이상을 의미 공백이 아닌문자가 아닌문자가 1개이상

12 자료파일 관리와 지속성

12.1 Donald Jon Bentley,MoreProgramming 자료 E. Knuth,LiterateProgramming,CSLI,1992 파일 Pearls,Addison-Wesley,1990 csv 파일 형식: 쉼표(',') (',')로 자료 구분 Entry{"DonaldE. "Literate E. Knuth", Programming", 루아 테이블을 사용하면 자료를 쉽게 구성 루아 테이블 Entry{"JonBentley", "CSLI", 1992} 1 "More "Addison-Wesley", 1990} Programming Pearls", Entry{author = "Donald E. Knuth", 루아 테이블 }Entry{ title publisher year = "Literate 1992 = "CSLI", Programming", 2 {이름 { 이름-값} author = "Jon Bentley", } title publisher year = "More 1990 = "Addison-Wesley", Programming Pearls",

12.2 직렬화 직렬화: 파일 저장 네트워크 전송 등 자료의 처리 순서가 명확히 요구되는 환경에서 자료를 바이트 또는 문자 스트림으로 변환하는 작업 순환 참조가 없는 단순 테이블 구조 해석 저장될 스트림을 분석해서 각각 수치, 문자열, 테이블 구조에 대한 코드 저장 function serialize (o) if type(o) == "number" then io.write(o) elseif type(o) == "string" then -- 문자열 저장 "%q"는 큰따옴표로 감싸는 것 " -->\"으로 변경됨 io.write(string.format("%q", ", o)) elseif type(o) == "table" then -- 테이블 스트림은 {} 안에 출력 io.write("{\n") ") for k,v in pairs(o) do io.write(" ", k, " = ") -- first version --[[ --second version io.write(" [") serialize(k) io.write("] = ") --]] serialize(v) io.write(",\n") ") io.write("}\n") ") else error("cannot serialize a ".. type(o))

12.2 직렬화 -- result of serialize{a=12, b='lua', key='another "one"'} -- first version { a = 12, b = "Lua", key = "another \"one "one\"", "", } -- second version { ["a"] = 12, ["b"] = "Lua", ["key"] = "another \"one "one\"", "", }

12.2 직렬화 순환 참조가 있는 테이블 저장 테이블에 테이블이 있는 구조는 이름이 필요. 이름과 값을 동시에 받아서 처리 function basicserialize (o) if type(o) == "number" then return tostring(o) else -- assume it is a string return string.format("%q", ", o) function save (name, value, saved) saved = saved or {} -- initial value io.write(name, " = ") if type(value) == "number" or type(value) == "string" then io.write(basicserialize(value), "\n")" elseif type(value) == "table" then if saved[value] then -- value already saved? io.write(saved[value], "\n") " -- use its previous name else saved[value] = name -- save name for next time io.write("{}\n") ") -- create a new table for k,v in pairs(value) do -- save its fields local fieldname = string.format("%s[%s]", name, basicserialize(k)) save(fieldname, v, saved) else error("cannot save a ".. type(value))

12.2 직렬화 --call save save('a', ', a) --result a = {} a[1] = {} a[1][1] = 3 a[1][2] = 4 a[1][3] = 5 a[2] = a a["y"] "] = 2 a["x"] "] = 1 a["z"] "] = a[1]

13 메타테이블 메타메서드

13 메타테이블과 메타메서드(Metatable and Metamethod) 메타테이블(metatable metatable): 루아에서 정의하지 되어 있지 않은 새로운 연산을 지정하는 방법 메타테이블 동작: 두 테이블의 연산에서 메타테이블과 '연산 필드' 필드가 있는지 먼저 확인 연산 함수가 존재하더라도 메타테이블에 '연산 필드'에 대한 메타메서드가 있으면 이 필드에 정의 된 함수를 먼저 실행 테이블에 대해서만 메타 테이블을 적용할 수 있음 문자열 라이브러리는 문자열 전용 메타테이블만 적용 t = {} print(getmetatable(t)) --> nil -- 메타테이블 적용 t1 = {} setmetatable(t, t1) -- t 테이블에 t1 assert(getmetatable(t) == t1) t1 테이블을 테이블을 메타테이블로 적용

13.1 산술 연산 메타메서드 산술 연산에 관련된 필드: '+': add, '-': sub, ' ': sub, '*': mul mul, '/': div, '-': ' ': unm <-- 부호 반전 '%': mod, '^': pow pow, '..': concat <-- 병합 연산 -- 집합(set) 자료구조에 대한 메서드 정의 Set = {} function Set.new (t) local set = {} for _, l in ipairs(t) do set[l] = true return set function Set.union (a,b a,b) -- 합집합 local res = Set.new{} for k in pairs(a) do res[k] = true for k in pairs(b) do res[k] = true return res function Set.intersection (a,b a,b) -- 교집합 local res = Set.new{} for k in pairs(a) do res[k] = b[k] return res

13.1 산술 연산 메타메서드 산술 연산에 관련된 필드: '+': add, '-': sub, ' ': sub, '*': mul mul, '/': div, '-': ' ': unm <-- 부호 반전 '%': mod, '^': pow pow, '..': concat <-- 병합 연산 집합의 합집합을 '+' 연산자로, 교집합을 '-' 연산자로 처리하는 방법 -- 집합(set) 자료구조에 대한 메서드 정의 Set = {} function Set.new (t) local set = {} for _, l in ipairs(t) do set[l] = true return set function Set.union (a,b a,b) -- 합집합 local res = Set.new{} for k in pairs(a) do res[k] = true for k in pairs(b) do res[k] = true return res function Set.intersection (a,b a,b) -- 교집합 local res = Set.new{} for k in pairs(a) do res[k] = b[k] return res

13.1 산술 연산 메타메서드 -- 집합 자료구조의 내용을 출력하기 위한 함수 function Set.tostring (set) local s = "{" local sep = "" for e in pairs(set) do s = s.. sep.. e sep = ", " return s.. "}" function Set.print (s) print(set.tostring(s))

13.1 산술 연산 메타메서드 -- '+' 연산자가 호출되면 합집합을 구하도록 메타테이블로 사용할 정규 테이블을 생성 Set.mt = {} -- '+' 연산자를 사용하기 위한 메타테이블 function Set.new (t) -- 집합 자료구조 생성 함수 수정. 2nd version local set = {} setmetatable(set, Set.mt) -- 메타테이블 설정 for _, l in ipairs(t) do set[l] = true return set -- Set.new() 로 생성된 모든 집합은 동일한 테이블을 자신의 메타테이블로 지정됨 s1 = Set.new{10, 20, 30, 50} s2 = Set.new{30, 1} print(getmetatable(s1)) --> table: print(getmetatable(s2)) --> table: -- 합집합 연산을 위해서 Set.mt에 add 추가 Set.mt. add = Set.union s3 = s1 + s2 -- '+' 연산자로 합집합 표현 Set.print(s3) --> {1, 30, 10, 50, 20} Set.mt. mul = Set.intersection -- 교집합 연산을 위해서 Set.mt에 mul 추가 Set.print((s1 + s2)*s1) -- +, * 연산자로 합집합, 교집합 연산 --> {30, 10, 50, 20} > {30, 10, 50, 20}

13.2 관계 연산 메타메서드 관계 연산 필드: '==': eq eq, '<': lt lt, '<=': le '~', '>', '>='은 다음 관계가 있어 별도의 메타메서드가 없음 a~=b <-- -->!(a==b), a>b <-- -->!(a<=b) a>=b <-- -->!(a<b) 산술 연산은 다른 타입을 섞어 사용할 수 있으나 관계 연산은 불가 항등 연산은 다른 타입을 쓸 수 있으나 다르면 항상 false --관계 연산 필드 정의 Set.mt. le = function (a,b a,b) -- set containment for k in pairs(a) do if not b[k] then return false return true

13.2 관계 연산 메타메서드 Set.mt. lt = function (a,b a,b) return a <= b and not (b <= a) -- 마지막으로 lt, le를 가지고 항등 비교 연산 정의 Set.mt. eq = function (a,b a,b) return a <= b and b <= a -- 메타메서드 정의 테스트 s1 = Set.new{2, 4} s2 = Set.new{4, 10, 2} print(s1 <= s2) --> true print(s1 < s2) --> true print(s1 >= s1) --> true print(s1 > s1) --> false print(s1 == s2 * s1) --> true

13.3 라이브러리 전용 메서드 연산 함수가 미리 존재하더라도 메타테이블에 '연산 필드'에 대한 메타메서드가 있으면 이 필드에 정의 된 함수를 먼저 실행 -- print는 언제나 포맷 때문에 tostring() 호출 print({}) --> table: -- 만약 연산 필드 tostring tostring에 대한 메타메서드가 --정의되어 있으면 이 메타메서드를 호출 Set.mt. tostring = Set.tostring s1 = Set.new{10, 4, 5} -- print() 함수에서 Set의 tostring이 호출됨 print(s1) --> {5, 10, 4} setmetatable/getmetatable 함수는 metafield를 사용하지만 이것은 메타 테이블을 보호하기 위한 것 -- 메타 테이블을 보호하기 위해 에러나 경고등에 대한 문자 설정 Set.mt. metatable = "메타테이블은 정의할 수 없음" s1 = Set.new{} print(getmetatable(s1)) --> "메타테이블은 정의할 수 없음" 출력 setmetatable(s1, {}) --> 오류 출력

13.4 테이블 접근 메타메서드 index 메타메서드: 테이블의 원소 접근 처리 테이블에 존재하지 않은 인덱스(키) 접근할 때 이를 처리 index 메타메서드의 활용은 키가 정해지지 않은 원소를 접근할 때 nil을 반환하거나 객체를 새로 생성해서 반환할 수 있는 장점 이 있음 Window = {} -- 이름 공간 생성 Window.prototype={x=0,y=0,width=200,height=300,} -- 기본값(Default) 설정 Window.mt = {} -- 메타테이블 생성 function Window.new (o) -- 생성자 함수 선언 print("call Window.new") setmetatable(o, Window.mt) return o -- index 메타메서드 설정 Window.mt. index = function (table, key) print("call index") return Window.prototype[key] -- 함수 대신 테이블로 직접 설정 Window.mt. index = Window.prototype -- 테스트 w = Window.new{x=10, y=20} print(w.width) --> 200 w.width에 접근. w["width"], "], Window.prototype Window.prototype와 동일 동일

13.4 테이블 접근 메타메서드 index 메타메서드: 테이블의 원소 접근 처리 테이블에 존재하지 않은 인덱스(키) 접근할 때 이를 처리 index 메타메서드의 활용은 키가 정해지지 않은 원소를 접근할 때 nil을 반환하거나 객체를 새로 생성해서 반환할 수 있는 장점 이 있음 Window = {} -- 이름 공간 생성 Window.prototype={x=0,y=0,width=200,height=300,} -- 기본값(Default) 설정 Window.mt = {} -- 메타테이블 생성 function Window.new (o) -- 생성자 함수 선언 print("call Window.new") setmetatable(o, Window.mt) return o -- index 메타메서드 설정 Window.mt. index = function (table, key) print("call index") return Window.prototype[key] -- 함수 대신 테이블로 직접 설정 Window.mt. index = Window.prototype -- 테스트 w = Window.new{x=10, y=20} print(w.width) --> 200 w.width에 접근. w["width"], "], Window.prototype Window.prototype와 동일 메타메서드를 함수로 설정하는 것이 테이블보다 비용이 많이 들지만 다중 상속, 캐시 처리, 기타 중간 작업 등을 설정할 수 있어 융통성이 높음 동일

13.4 접근 메타메서드 Window.mt. newindex= --index 테이블갱신 메타메서드설정 갱신처리 처리. 존재하지않은 않은인덱스 인덱스(키)에값을 값을설정할 설정할때처리 newindex print("call Window.prototype[key] newindex") function = value (table, key, value) w.height= w --테스트 print(w.height) = Window.new{x=10, 30 y=20} --table table안에 안에직접 직접수정 -->30 -->w.height w.height에접근 접근. t index = { =, function print("*access return t[k] (temp, to k) element ".. tostring(k)) newindex newindex= function (temp, k,, print("*update t[k] = v " to " of.. element tostring(v)) ".. tostring(k).. }function print("callt.new t.new(o) t.new") return setmetatable(o, o t) print(w[3]) w = t.new{} = "Hello" --> > *access *update to of element 3, 3 to hello hello,] = v

13.4 테이블 접근 메타메서드 테이블 접근 추적하기 index 와 newindex newindex를 혼합 사용해서 대행자(proxy) (proxy)를 만들어 존재하지 않은 키에 대한 처리 t = {} -- 테스트용 원본 테이블 local _t = t -- 원본 테이블을 비공개 접근 유지하도록 local에 저장 t = {} -- 대행자(proxy (proxy) 생성 -- 메타테이블 생성 local mt = { index = function (t,k t,k) print("*access to element ".. tostring(k)) return _t[k t[k] -- 원본 테이블 접근, } newindex = function (t,k,v t,k,v) print("*update of element ".. tostring(k).. " to ".. tostring(v)) _t[k t[k] = v -- 원본 테이블 갱신 setmetatable(t, mt) -- test t[2] = "hello" --> *update of element 2 to hello print(t[2]) --> *access to element 2, hello

14 환경

14 환경 루아는 전역변수를 환경 테이블에 저장 전역 변수를 저장한 _G table 출력 for n in pairs(_g) do print(n) 환경 변수 설정 함수: setfenv() 필드를 수정하는 함수: setfield()

14.1 동적 명칭을 가진 전역 변수 다른 변수에 담긴 문자열을 전역 변수 이름으로 사용하거나 실행 시점에 전역 변수 이름을 만들 필요가 있을 때 패 턴을 사용해서 일반화 시킴 function getfield (f) local v = _G -- 전역 테이블을 사용하여 시작 for w in string.gfind(f, "[%w_]+") do v = v[w] print(v) return v --[%w_]+ 은 영문자 '_' 가 반복되는 패턴: 전역 변수 테이블에는 '_'로 시작하는 변수도 존재함 function setfield (f, v) local t = _G -- 전역 테이블을 사용하여 시작 for w, d in string.gfind(f, "([%w_]+)(.?)") do if d == "." then -- 마지막 필드가 아니라면 t[w] = t[w] or {} -- 없다면 새로운 필드를 만듦 t = t[w] -- 테이블을 얻는다. else -- 마지막 필드라면 t[w] = v -- 값을 할당한다. --([%w_]+)(.?) 은 영문자와 '_'의 조합 패턴에 마지막에 '.' 0번 0 또는 1번 있을 때를 의미 -- 테이블 t에.x.y 를 생성하고 10d을 배정 setfield("t.x.y", ", 10) print(t.x.y) --> 10 print(getfield("t.x.y")) ")) --> 10

14.2 전역 변수 선언 -- 존재하지 않은 전역 변수에 대한 접근을 에러로 처리 -- 다음 코드는 lua.exe에서는 중단됨 setmetatable(_g, { index = function (_, n) error("attempt to read undeclared variable "..n, 2), newindex newindex=function (_, n) error("attempt to write to undeclared variable "..n, 2), }) --a는 선언이 되지 않아 오류 메시지를 출력 a = 1 -->stdin:1: attempt to write to undeclared variable a 새로운 변수의 선언은 메타메서드를 건너뛰는 rawset() 함수 사용 function declare (name, initval) rawset(_g, name, initval or false) -- nil 값 대신 false false 값으로 값으로 대치

14.3 비전역 환경 루아의 환경은 전역변수를 사용하므로 전역 변수가 수정되었을 때 전체 환경이 달라짐 루아 5 이상은 함수마다 자신만의 환경을 가지도록 구성됨 환경 변경 함수 : setenv() -- 전역 변수 선언 검사 local declarednames={} setmetatable(_g, { newindex = function(t, n, v) if not declarednames[n] then local w = debug.getinfo(1, "S").what if w ~= "main" and w ~= "C" then error("attempt to write to undeclared variable "..n, 2) declarednames[n] = true rawset(t, n, v), }) --test a= 1 setfenv(1, {}) --현재 환경을 새로운 빈 테이블로 변경 print(a) -- stdin:5: attempt to call global 'print' (a nil value)

14.3 비전역 환경 환경을 변경하면 전역 접근은 새로운 테이블을 사용 --_G 이름으로 환경을 변경하고 다시 배정 a = 1 -- create a global variable setfenv(1, {_G = _G}) -- 현재 환경 변경 _G.print(a G.print(a) --> nil _G.print(_G.a G.print(_G.a) --> 1 -- 상속을 사용한 환경 변경 a = 1 local newgt = {} -- 새로운 환경 생성 setmetatable(newgt, { index = _G}) setfenv(1, newgt) -- 생성한 환경 설정 print(a) --> 1 a = 10 print(a) --> 10 print(_g.a) --> 1 _G.a = 20 print(_g.a) --> 20

15-19 19 모듈, 테이블, 객체지향, 라이브러리

15.1 루아 모듈 모듈 모듈: 거의 독립된 기능을 가지면서 교환 가능한 실행단위 패키지 :모듈의 모음 루아의 모듈은 require 함수를 통해서 읽고 테이블에 저장하는 단일한 전역 이름으로 이 름공간(namespace) (namespace)처럼 동작 모듈 구성: 함수, 상수 모듈은 일등급 값이 아님 모듈 호출 방법 require "mod" -- 모듈 호출 mod.foo() -- 모듈내의 함수 실행 local m = require "mod" -- 모듈을 호출하고 변수 m에 저장 m.foo() require "mod" -- 모듈 호출 local f = mod.foo() -- 모듈의 함수를 변수에 저장 f() -- io 에 대한 모듈 사용 예 local m = require "io io" m.write("hello world\n")

15.2 모듈 작성 테이블을 만들고, 내보낼 모든 함수를 넣고 테이블을 반환함 complex = {} -- 복소수에 대한 모듈 function complex.new (r, i) return {r=r, i=i} -- 생성 complex.i = complex.new(0, 1) -- 허수부에 대한 상수 정의 function complex.add (c1, c2) -- 덧셈 return complex.new(c1.r + c2.r, c1.i + c2.i) function complex.sub (c1, c2) -- 뺄셈 return complex.new(c1.r - c2.r, c1.i - c2.i) function complex.mul (c1, c2) -- 곱셈 return complex.new(c1.r*c2.r - c1.i*c2.i, c1.r*c2.i + c1.i*c2.r) function complex.inv (c) -- 역수 local n = c.r^2 + c.i^2 return complex.new(c.r/n, -c.i/n c.i/n) return complex -- 테이블 반환 -- test c = complex.add(complex.i, complex.new(10, 20)) print(c.r, c.i) -->10 21

16 객체지향 프로그래밍 루아의 자료구조는 테이블로 구성되기 때문에 원칙적으로 객체 지 향 프로그램을 할 수 없고 비슷하게 흉내낼 수 있음 객체 자신의 함수 참조: self 또는 this 이용 self: 명령의 수신자(receiver). this와 비슷 v = 10 Account = {balance = 0} function Account.withdraw (self, v) self.balance = self.balance - v a1 = Account; Account= nil -- a1.withdraw(a1, 100.00) -- widthdraw 함수 함수 인수에 인수에 a1을 전달함

16 객체지향 프로그래밍 콜론(':') : 메서드 변수의 접근에 대한 범위 연산자 Account = { balance=0, withdraw = function (self, v) self.balance = self.balance - v print("widthdraw ", self.balance) } function Account:deposit (v) self.balance = self.balance + v print("deposit ", self.balance) a1 = Account; Account= nil -- a1.deposit(a1, 200.00) a1:withdraw(100.00) -- -- a1.withdraw(a1, 100.00) a1.withdraw(a1, 100.00)과 같음

17 약 참조 테이블 (Weak Table) 루아는 Garbage Collector가 있어 더 이상 참조가 없는 객체들을 자동으로 수거 만약 객체가 집합 (Set)에 있으면 자동으로 수거 안됨 약 참조 테이블: 위치에 관계 없이 자동으로 수거될 대상 강 참조 테이블: 키와 값 모두 자신이 참조하는 객체의 수거를 방해함으로 strong reference라 함 mode로 수정: 문자열로 설정 약 참조 키 설정: mode ="k" 약 참조 값 설정 : mode ="v" a = {} b = { mode = "k"} setmetatable(a, b) -- a는 약참조 키를 가짐 key = {} -- 첫 번째 키 생성 a[key] = 1 key = {} -- 두 번째 키 생성 a[key] = 2 collectgarbage() -- 강제로 garbage collector 실행 for k, v in pairs(a) do print(v) --> 2

18 수학 라이브러리 수학 함수들: sin, cos, tan, asin, acos, exp, log, log10, floor, ceil, amx, min, random, randomseed 모든 삼각 함수는 radian으로 동작 수학 함수들을 다시 정의 하는 방법 -- sin, cos, tan, asin, acos local sin, cos, tan, asin, acos = math.sin, math.cos, math.tan, math.asin, math.acos -- degree, radian 변환 local deg, rad = math.deg, math.rad -- sin 함수의 입력 각도를 radian으로 설정 math.sin = function (x) return sin(rad(x)) -- sin 함수의 입력 각도를 degree로 설정 math.asin = function (x) return deg(asin(x)) math.random(n) 정수 [1, n] 값을 반환. 인수가 없으면 [0, 1) 실수 값을 반환 seed가 설정되어 있지 않으면 매번 동일한 값 출력 math.randomseed(seed): 난수의 seed 값을 지정 math.randomseed(os.time()) ())

19 테이블 라이브러리 insert(테이블 테이블, 위치, 원소): 지정 위칭 원소 추가. 위치 가 없으면 맨 끝에 추가 t = {10, 20, 30} table.insert(t, 1, 15) for i, n in pairs(t) do print(n) --getn getn() 테이블 원소 수 반환 print(table.getn(t)) sort(t): 정렬 table.sort(t, f) concat(): 병합

20 문자열 (string) 라이브러리 byte(): 구간의 문자를 숫자로 반환 char(): 숫자를 ASCII로 변환 len(): 문자열 길이 반환 lower(): 소문자로 전환 upper(): 대문자로 전환 reverse(): 역순으로 변경 sub(): 구간 i, j 사이의 문자열 추출. j=-1 문자열 마지막 글자 j=-2 그 이전 문자 gmatch(): 문자열에서 패턴과 일치하는 모든 부분을 훑어 나감. -- 문자열 s 안의 모든 문자 수거 예제 words={} for w in string.gmatch(s, "a+") do words[#words +1] = w

20 문자열 (string) 라이브러리 format(): C의 printf() 함수의 포맷 설정과 동일 find(대상 문자열, 패턴): 문자열 검색. 시작 위치, 끝 위치 두개의 값을 반환 i, j = string.find("hi, Hello world", "Hello") print(i, j) --> 5, 9 gsub(대상 문자열, 패턴, 대체할 문자열): 문자열 대체 s = string.gsub("lua is cute", "cute", "great") print(s) --> Lua is great 패턴: 문자 분류(character class)와 마법문자(magic character)를 이용 문자 분류:., %a, %c, %d, %l, %p, %s %u %w %x %z 마법문자: ( ). % + - *? [ ] ^ $ 알파벳, 숫자, _ 패턴: [A-Za Za-z0 z0-9_] 주민 번호 : \d{6} d{6}-\d{7} d{7} 16진수 진수: [A-Fa Fa-f0 f0-9]

21 입출력(io io) 라이브러리 open(): 파일 입출력 핸들 얻음. "r, "w" 모드 필요 close(): 파일 핸들 닫기 input(): 읽기 모드로 파일 오픈 output(): 쓰기 모드로파일 오픈 read(): 파일을 읽어 들임. *all을 사용하면 전부 읽음 local fd = io.open(loadname) local slotnum = fd:read(3) fd:close() write(): 파일에 쓰기 lines(): line 단위로 읽기 close(): open()으로 개방한 파일 닫기 seek(): 파일 포인터 위치 옮기기 "set" 시작 위치, "" 파일 끝

21 입출력(io io) 라이브러리 -- 텍스트 파일 읽기 연습 fr = io.open ("test.txt","r test.txt","r") ") -- 파일 핸들 얻기 while true do local line = fr:read("*line") -- 라인단위로 파일 내용 읽기 if nil == line then -- 읽을 데이터가 없으면 nil 반환 break print(line) -- 라인 내용 출력 fr:close() -- 파일 핸들 반환

22 운영체제 라이브러리 date(): 날짜 print(os.date()) ()) time(): 시간 print(os.time()) ()) getenv(): 시스템 환경 변수 os.getenv("path") ") execute(): 프로그램 실행 os.execute("notepad.exe") ")