Object.create 함수로 크로스 브라우저 호환성 보완
*/
(function () { if(!Object.create) { Object.create = (function () { function F() {} return function (o) { F.prototype = o; return new F(); } })(); } });
(function () { if(!Object.create) { Object.create = (function () { function F() {} return function (o) { F.prototype = o; return new F(); } })(); } });
/* class와 extends를 통한 상속 자바스크립트의 new기능의 모호함을 해소하기 위해 ECMA6에서는 class와 extends를 정의한다. */ class Person { constructor() { this.name = "anonymous"; } } class User extends Person { constructor() { super(); this.name = "User"; } } var user1 = new User(); console.log(user1 instanceof Person); console.log(user1 instanceof User); console.log(user1.constructor); // [Class: user]
/* Object.create와 new 키워드 조합 Object.create과 new 키워드를 조합하여 생성자의 연결이 깨지지 않도록 해보자. */ function Person() { this.name = "unknown"; } function User() { this.name = "user"; } // 두 번째 매개변수는 키는 속성명으로 // 새로 만든 객체에 추가될 속성 설명자(descriptor)를 지정합니다. // writable option defaults to false. // https://stackoverflow.com/questions/7757337/defining-read-only-properties-in-javascript User.prototype = Object.create(Person.prototype, { constructor: { // Person.prototype.constructor 는 이제 읽기전용이다. value: User // 왜냐하면 기본이 writable = false 이다. } }) var myuser = new User(); console.log(myuser instanceof User); console.log(myuser instanceof Person); console.log(myuser.constructor);이 녀석은 이전
function Car() { this.wheel = 4; this.beep = "BEEP"; } Car.prototype.go = function () { alert(this.beep); }; function Truck() { this.wheel = 6; this.beep = "TRUCK!!"; } Truck.prototype = new Car(); function SUV() { this.beep = "SUV!!"; } SUV.prototype = new Car(); var truck = new Truck(), suv = new SUV(); console.log(truck.wheel); // 6 console.log(suv.wheel); // 4 console.log(truck.beep); // TRUCK!! console.log(suv.beep); // SUV!!Car라는 객체를 프로토타입에 넣어보니
// 실제로는 Object.create 이라는 함수가 있다. 더글라스 크락포드가 주장했던 함수형태 Object.my_create = function(o) { function F() {}; F.prototype = o; // O는 처음부터 prototype역할을 하는 녀석일 것이다. return new F(); } function Person(name) { this.name = name; } Person.prototype = { yell: function() { alert("My name is " + this.name); } }; var u = Object.my_create(Person.prototype); // prototype을 넘기는 것을 주의하자. u.name = "U"; u.yell(); // alert /* 이렇게 Object.create 함수를 통해 객체를 생성하면 개발자가 new 키워드를 사용하지 않고 함수 호출로 객체가 생성된다. new 키워드를 사용할 때와는 달리 전체적으로 소스에 생성자의 개념이 사라지고 (new가 없으니까) 객체의 인스턴스와 인스턴스 간의 상속을 강조하는 것이 Object.create의 특징 (???) */
function Person() { this.name = "anomymous"; this.sayHello = function() { console.log(this.name + "!!"); }; } function Nam() { this.name = "Nam"; } Nam.prototype = new Person(); var nam = new Nam(); nam.sayHello(); console.log(nam instanceof Nam); // true console.log(nam instanceof Person); // true console.log(nam.constructor); // ?? Nam이 아니라 Person!! /* 생성자 속성은 객체가 가지고 있는 것이 아니라. 프로토타입이 가지고 있다. 객체는 내부 링크로 프로토타엡에 있는 생성자 속성을 참조한다. 지금 Nam프로토타입은 그런데 new Person()으로 원래 객체(여기선 Nam)의 생성자를 가지고 있는 프로토타입을 덮어씌우면 Nam의 생성자는 연결고리를 잃는다. (원래 Nam의 생성자는 function Nam() {...} 을 가리키고 있어야 한다.) 따라서 nam.constructor를 실행하면 [Function: Person] 이 나온다. 뭐 잘 작동하기는 하지만 연결이 끊어진다는 것은 좋은 것이 아니다. */
public static Unsafe getUnsafe() { Class cc = sun.reflect.Reflection.getCallerClass(2); if (cc.getClassLoader() != null) throw new SecurityException("Unsafe"); return theUnsafe; }여기서 볼 수 있듯이 일단 theUnsafe라는 녀석이 싱글턴 인스턴스다.
public void getUnsafe() throws Exception { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafe.get(null); System.out.println(unsafe); }이렇게 하면 되지만 안드로이드에서는 Unsafe클래스의 이름이 "theUnsafe"가 아니라. THE_ONE이라는 이름으로 불린다고 하니 이런 코드는 플랫폼에 의존적이다.
public Unsafe getUnsafeInstance() throws Exception { ConstructorunsafeConstructor = Unsafe.class.getDeclaredConstructor(); Unsafe unsafe = unsafeConstructor.newInstance(); System.out.println(unsafe); return unsafe; }
package volatile_test; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class VolatileTest1 { private volatile static int counter = 0; public static void main(String[] args) { Runnable r1 = () -> { System.out.println(counter); counter++;}; ExecutorService es = Executors.newCachedThreadPool(); for(int i = 0; i < 10; i++) { es.execute(r1); } es.shutdown(); // OUTPUT // 0 // 0 // 0 // 3 // 4 // 5 // 6 // 7 // 8 // 9 } }0이 3번이나 나왔다. 왜그럴까? 특이한 것은 결과적으로 +1이 잘 되었지만 조회가 잘 안되었다는 것인데 다시 한 번 해보자.
0 0 0 0 0 0 6 6 8 8전혀 다른 값이 나왔다. 그 말은 값이 달라졌다는 것이다. volatile을 사용한다고 동기화가 되는 것이 아니다. 읽기-수정-쓰기 가 동기화가 되야 하는 것이다. 그렇다면 volatile은 언제 써야 할까? 아래와 같은 경우를 보자.
package volatile_test; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class VolatileTest2 { // 아래 내용을 보자. 과연 잘 돌아가는 경우가 얼마나 있을까? private static boolean flag = true; public static void main(String[] args) { Runnable r1 = () -> { while(flag) { // 여기에 막히게 된다. } System.out.println("bye"); }; Runnable r2 = () -> { System.out.println("flag false start"); flag = false;}; ExecutorService es = Executors.newCachedThreadPool(); for(int i = 0; i < 10; i++) { es.execute(r1); } es.execute(r2); es.shutdown(); } }여기서는 전혀 돌아가지는 않는다. 이것은 volatile의 부재일 수도 있지만, 컴파일러 마다 최적화를 하면서 결과값이 다르게 나올 수도 있다고 한다. 여튼 위 내용은 현재 flag를 false로 변경했지만 먹히지 않는다. 이때 volatile을 넣어보자.
package volatile_test; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class VolatileTest3 { // 이럴때 volatile로 바꾸는 것만으로 효과가 있다. private volatile static boolean flag = true; public static void main(String[] args) { Runnable r1 = () -> { while(flag) { // System.out.println("hi"); } System.out.println("bye"); }; Runnable r2 = () -> { System.out.println("flag false start"); flag = false;}; ExecutorService es = Executors.newCachedThreadPool(); for(int i = 0; i < 10; i++) { es.execute(r1); } es.execute(r2); es.shutdown(); } }
import random import string import csv import datetime import calendar random_numbers = set() for _ in range(120): res = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(16)) random_numbers.add(res) def add_months(sourcedate, months) -> datetime.date: month = sourcedate.month - 1 + months year = sourcedate.year + month // 12 month = month % 12 + 1 return datetime.date(year,month,1) somedate = datetime.date(2018, 4, 1) with open('random_number.txt', 'w', newline='\n') as f: w = csv.writer(f, delimiter=' ', quoting=csv.QUOTE_NONE) for idx, num in enumerate(random_numbers): w.writerow([add_months(somedate, idx).strftime('%Y-%m'), num]) # print(len(random_numbers))
def solution(N, A): res = [0] * N max_counter = 0 for a in A: if a <= N: # N카운터 존재 res[a-1] +=1 # 카운터 올림 if max_counter < res[a-1]: # max_counter 보다 크면 현재 카운터를 tmp_max로 변경 max_counter = res[a-1] else: # max counter 실행 for i in enumerate(res): # 전부 max_counter로 덮어씌운다. res[i] = max_counter return res빅오노테이션이 O(MxN) 인 관계로 이중포문에서 하나를 없애야 한다.
# N 카운터가 있음. 0으로 세팅 # max counter : 모든 카운터들이 아무 카운터의 최대 값으로 세팅됨. # A[K] = X 이면, K오퍼레이션은 X를 증가시킨다. # -> 값이 X면 X를 증가시킴 (X범위 1<=X<=N) # A[K] = N + 1 이면 K는 max counter (??? K가 N보다 크면 max??) # 아아아 max counter라는 걸 실행함!!! def solution(N, A): res = [0] * N max_counter = 0 tmp_max = 0 for a in A: if a <= N: # N카운터 존재 if max_counter > res[a-1]: # 1 max_counter가 더 크면 max_counter가 갱신된 것 res[a-1] = max_counter # 2 max_counter 값으로 변경해준다. res[a-1] +=1 # 3 그리고 그 다음에 카운터 시킨다 if tmp_max < res[a-1]: # 4 tmp_max보다 크면 현재 카운터를 tmp_max로 변경 tmp_max = res[a-1] else: # max_counter 에 현재 tmp_max를 넣는다. (max_counter는 그때그때 실행할 것이다.) max_counter = tmp_max # 아직 max_counter가 변경 된 이후에 counter가 변경된 이력이 없으면 max_counter로 덮어씌워준다. # 물론 max_counter보다 작은 경우. for idx, _ in enumerate(res): if (res[idx] < max_counter): res[idx] = max_counter return res a = [3,4,4,6,1,4,4] N = 5 print(solution(5, a))
# Determine how many pairs of astronauts from different countries they can choose from. # UN 연합은 달에 사람들을 보내려고 한다. # 그들은 이 사람들이 서로 다른 나라였으면 한다. # 당신은 두 쌍의 우주조종사 id 리스트를 받을 것이다. # 각 쌍은 같은 나라 우주조종사 id의 두 쌍으로 이루어져 있다. # - 얼마나 많은 조종사 쌍을 만들 수 있는지 말해라. # n : number of astronaut # p : the number of pairs from collections import defaultdict # 일단 연결된 것들을 만든다. def dfs(graph, start): visited, stack = set(), [start] while stack: v = stack.pop() visited.add(v) # 해당 정점에 연결된 것들을 stack에 넣는다. # 방문한 것은 제외 stack.extend(graph[v] - visited) # 연결된 것들을 리턴. return visited def journeyToMoon(n, ast_pairs): graph = defaultdict(set) asts = set() # 그래프 연결... for a1, a2 in ast_pairs: graph[a1].add(a2) graph[a2].add(a1) asts.add(a1) asts.add(a2) # 고립된 애들이 있을 수 있나? 일단 받아놔... (있는듯...) iso_asts = set([i for i in range(n)]) - asts groups = [] # divied by contry while asts: ast = asts.pop() connected_asts = dfs(graph, ast) groups.append(connected_asts) # 한번 방문한 팀은 다시 방문하지 않는다. asts = asts - connected_asts for i in iso_asts: groups.append({i}) idx1, idx2 = 0, 1 group_sum = 0 while idx1 < len(groups)-1: idx2 = idx1 + 1 while idx2 < len(groups): group_sum += len(groups[idx1]) * len(groups[idx2]) idx2 += 1 idx1 += 1 return group_sum n, p = list(map(int, input().strip().split(' '))) ast_pairs = [] for _ in range(p): astronaut = [int(a) for a in input().strip().split(' ')] ast_pairs.append(astronaut) result = journeyToMoon(n, ast_pairs) print(result)
def dfs(graph, start): visited, stack = set(), [start] while stack: v = stack.pop() visited.add(v) stack.extend(graph[v] - visited) return visited def journeyToMoon(n, ast_pairs): graph = defaultdict(set) asts = set() for a1, a2 in ast_pairs: graph[a1].add(a2) graph[a2].add(a1) asts.add(a1) asts.add(a2) iso_asts = set([i for i in range(n)]) - asts groups = [] # divied by contry while asts: ast = asts.pop() connected_asts = dfs(graph, ast) groups.append(connected_asts) # 한번 방문한 팀은 다시 방문하지 않는다. asts = asts - connected_asts for i in iso_asts: groups.append({i}) # 뒤에 추가된 것들을 따로 분리해야 한다. 그래야 추가된 녀석들이 만드는 # 패턴을 알 수 있다. # A*B + A*C + B*C -- A*B + A*C + B*C -- A*B + (A+B)*C # A*B + A*C + A*D + B*C + B*D + C*D # - A*B + (A+B)*C (A+B+C)*D # A*B + A*C + A*D + A*E + B*C + B*D + B*E + C*D + C*E + D*E # - A*B + (A+B)*C + (A+B+C)*D + (A+B+C+D)*E idx1, idx2 = 0, 1 group_sum = 0 tmp_sum = 0 while idx1 < len(groups): group_sum += tmp_sum*len(groups[idx1]) tmp_sum += len(groups[idx1]) # group_sum += tmp_sum*(len(groups[idx1 + 1])) idx1 += 1 return group_sum n, p = list(map(int, input().strip().split(' '))) ast_pairs = [] for _ in range(p): astronaut = [int(a) for a in input().strip().split(' ')] ast_pairs.append(astronaut) result = journeyToMoon(n, ast_pairs) print(result)
function Person(name) { this.name = name; } Person.prototype = { yell: function() { console.log("my name is " + this.name); } } /* 수정불가 */ var user = Object.create(Person.prototype, { name: { value: 'new name' } }) /* 수정가능 */ user = Object.create(Person.prototype, { name : { value: 'new name2', configurable: true, enumerable: true, writable: true } }) /* 접근자 활용의 예 */ Object.defineProperties(user, { firstName: { value: "Younghwan", writable: true }, lastName: { value: "Yang", writable: true }, fullName: { get: function() { return this.firstName + " " + this.lastName; }, set: function(value) { var res = value.split(' '); if (res.length > 1) { this.firstName = res[0]; this.lastName = res[1]; } else { console.log('wrong format'); } } }); console.log(user.fullName); user.fullName = "Hello world!"; console.log(user.firstName); // Hello console.log(user.lastName); // World!
-- 식 data Expr a = Plus (Expr a) (Expr a) -- 덧셈의 식 | Square (Expr a) -- 제곱의 식 | Number a -- 숫자의 식위 내용으로 식에 대한 정의는 끝났다.
-- 식의 평가를 실시하는 함수 evalExpr :: Expr Int -> Int evalExpr (Plus e1 e2) = evalExpr e1 + evalExpr e2 evalExpr (Square e) = evalExpr e ^ (2 :: Int) evalExpr (Number n) = n -- 식을 문자열로 하는 함수 showExpr :: Expr Int -> String showExpr (Plus e1 e2) = showExpr e1 ++ " + " ++ showExpr e2 showExpr (Square e) = "(" ++ showExpr e ++ ")^2" showExpr (Number n) = show n이것도 이렇게 끝났다. 간단하다.
main :: IO () main = do -- e = 1 + (2 + 3)^2 let e = Plus (Number 1) (Square (Plus (Number 2) (Number 3))) putStrLn (showExpr e) print (evalExpr e)
interface Visitor{ R plus(Expr e1, Expr e2); // 덧셈 식을 위한 메소드 R square(Expr e); // 제곱 식을 위한 메소드 R number(N n); // 숫자를 위한 메소드 }
interface Expr{ R accept(Visitor v); class Plus implements Expr { Expr e1; Expr e2; public Plus(Expr e1, Expr e2) { this.e1 = e1; this.e2 = e2; } @Override public R accept(Visitor v) { return v.plus(e1, e2); } } class Square implements Expr { Expr e; public Square(Expr e) { this.e = e; } @Override public R accept(Visitor v) { return v.square(e); } } class Number implements Expr { N n; public Number(N n) { this.n = n; } @Override public R accept(Visitor v) { return v.number(n); } }
// 식의 평가를 실시하는 Visitor class Eval implements Visitor{ @Override public Integer plus(Expr e1, Expr e2) { return e1.accept(this) + e2.accept(this); } @Override public Integer square(Expr e) { Integer x = e.accept(this); return x; } @Override public Integer number(Integer n) { return n; } } // 식을 문자열로 하는 Visitor class Show implements Visitor { @Override public String plus(Expr e1, Expr e2) { return e1.accept(this) + " + " + e2.accept(this); } @Override public String square(Expr e) { return "(" + e.accept(this) + ")^2"; } @Override public String number(Integer n) { return n + ""; } }
public class TestVisitor { public static void main(String[] args) { // e = 1 + (2 + 3) ^ 2 // 실제로는 구문 해석 등에 의해서 좀 더 크고 복잡한 것을 가정 Expr e = new Plus(new Number(1), new Square(new Plus(new Number(2) ,new Number(3)))); System.out.println(e.accept(new Show())); System.out.println(e.accept(new Eval())); } }
package org.test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Optional; import java.util.function.BiFunction; public class TestOptional { // 공백으로 분할하기, 세 개로 분할할 수 없으면 무효! private static Optionalwords(String expr) { String[] res = expr.split(" "); if (3 == res.length) { return Optional.of(res); } else { return Optional.empty(); } } // 문자열을 정수로 변환, 변활할 수 없으면 무효 private static Optional toNum(String s) { try { return Optional.of(Integer.parseInt(s)); } catch (NumberFormatException ex) { return Optional.empty(); } } private static Optional add(Integer a, Integer b) { return Optional.of(a + b); } private static Optional sub(Integer a, Integer b) { return Optional.of(a - b); } private static Optional mul(Integer a, Integer b) { return Optional.of(a * b); } private static Optional div(Integer a, Integer b) { if (a != b) { return Optional.of(a / b); } else { return Optional.empty(); } } // +-*/ 외 문자 무효 private static Optional >> toBinOp(String s) { switch(s) { case "+" : return Optional.of(TestOptional::add); case "-" : return Optional.of(TestOptional::sub); case "*" : return Optional.of(TestOptional::mul); case "/" : return Optional.of(TestOptional::div); default : return Optional.empty(); } } public static void main(String[] args) throws IOException { String expr = new BufferedReader(new InputStreamReader(System.in)).readLine(); // 마치 haskell의 Monad같은 모습. System.out.println( words(expr) .flatMap(ss -> toNum(ss[0]) .flatMap(a -> toBinOp(ss[1]) .flatMap(op -> toNum(ss[2]) .flatMap(b -> op.apply(a, b))))) .map(n -> "" + n) .orElseGet(() -> "invalid")); } } }
Optional저 위에 있는 것들로 테스트를 해보면 empty()를 뱉는 순간 다음 내용으로 if-else문으로 이어지지 않음을 알 수 있다.str = Optional.ofNullable("AB"); //Optional str = Optional.ofNullable("ABC"); //Optional str = Optional.ofNullable("ABCD"); str.flatMap(ss -> { if (ss.length() > 3) {System.out.println("FlatMap1 fail");return Optional.empty();} else {System.out.println("flatMap1 pass"); return Optional.of(ss.toLowerCase());} }).flatMap(ss2 -> { if (ss2.length() > 4) {System.out.println("FlatMap2 fail"); return Optional.empty();} else {System.out.println("FlatMap2 pass");return Optional.of(ss2.toUpperCase() + "@#$");} }).ifPresent(System.out::println);
-- Optional.hs -- $ stack ghc Optional.hs -- Optiona.exe -- 1 + 1 -- Optiona.exe -- 4 / 0 -- 문자열을 정수로 변환. 변환할 수 없다면 무효 toNum :: String -> Maybe Int toNum s = case reads s of [(n,"")] -> Just n -- 저절로 변환됨. _ -> Nothing -- 사칙연산. 연산할 수 없다면 무효 addOp :: Int -> Int -> Maybe Int addOp a b = Just (a + b) subOp :: Int -> Int -> Maybe Int subOp a b = Just (a - b) mulOp :: Int -> Int -> Maybe Int mulOp a b = Just (a * b) divOp :: Int -> Int -> Maybe Int divOp _ 0 = Nothing divOp a b = Just (a `div` b) -- +-*/ 연산 변환, 나머지 무효 toBinOp :: String -> Maybe (Int -> Int -> Maybe Int) toBinOp "+" = Just addOp toBinOp "-" = Just subOp toBinOp "*" = Just mulOp toBinOp "/" = Just divOp eval :: String -> Maybe Int eval expr = do -- 스페이스로 분할 let [sa, sop, sb] = words expr a <- toNum sa -- 문자열을 숫자로 op <- toBinOp sop -- 문자열을 연산자로 b <- toNum sb -- 문자열을 숫자로 a `op` b -- 연산 main :: IO () main = getLine >>= putStrLn . maybe "invalid" show . eval
Main> :t eval eval :: String -> Maybe Int Main> :t show show :: Show a => a -> String Main> :t show . eval show . eval :: String -> String Main> :t maybe maybe :: b -> (a -> b) -> Maybe a -> b Main> :t maybe "invalid" show . eval maybe "invalid" show . eval :: String -> [Char]자 보자.
Main> eval "1 + 1" Just 2 Main> (show . eval) "1 + 1" "Just 2" Main> (maybe "invalid" show . eval) "1 + 1" "2" Main> putStrLn $ (maybe "invalid" show . eval) "1 + 1" 2 Main> let a = putStrLn . maybe "invalid" show . eval Main> a "1 + 1" 2
-- Coord.hs -- $runghc Coord.hs import Text.Printf -- 좌표의 타입 type Coord = (Double, Double) -- 좌표 변환 설정 data Config = Config { rotAt :: Coord -- 회전 중심 좌표 , theta :: Double -- 회전량[라디안] , ofs :: (Double, Double) -- 병행 이동량 } -- 좌표 변환 함수의 타입은 "좌표를 별도의 좌표로 이동"하는 함수 -- "좌표를 받아서 좌표를 뱉는 함수"타입 type CoordConverter = Coord -> Coord -- 병행 이동의 프리미티브 trans :: Coord -> CoordConverter trans (dx, dy) = \(x, y) -> (x+dx, y+dy) --회전의 프리미티브 rotate :: Double -> CoordConverter rotate t = \(x, y) -> (cos t * x - sin t * y, sin t * x + cos t * y) -- 설정을 베이스로 한 병행 이동 transByConfig :: Config -> CoordConverter transByConfig config = trans (ofs config) -- 설정을 베이스로 한 회전 rotateByconfig :: Config -> CoordConverter rotateByconfig config = postTrans . rotate (theta config) . preTrans where rotateAt = rotAt config preTrans = trans(rotate pi $ rotateAt) postTrans = trans rotateAt convertByConfig :: Config -> CoordConverter convertByConfig config = transByConfig config . rotateByconfig config main :: IO () main = do let config = Config { rotAt = (0.5, 0.5), theta = pi / 4, ofs = (-0.5, -0.5)} let unitRect = [(0,0),(0,1),(1,1),(1,0)] let convertedRect = map (convertByConfig config) unitRect mapM_ (uncurry $ printf "(%.6f, %.6f)\n") convertedRect -- mapM_ is useful for executing something only for its side effects. -- https://stackoverflow.com/questions/27609062/what-is-the-difference-between-mapm-and-mapm-in-haskell
Prelude> let a = (*2) . length Prelude> a [1,2,3,4] 8이 형태는 수학적인 표기법과 아주 비슷하다.
Prelude> curry fst 1 2 1 Prelude> :t curry curry :: ((a, b) -> c) -> a -> b -> c Prelude> :t fst fst :: (a, b) -> a Prelude> :t curry fst curry fst :: c -> b -> c Prelude> curry fst error!! Prelude> curry fst 1 2 1
Prelude> :t uncurry uncurry :: (a -> b -> c) -> (a, b) -> c Prelude> :t (+) (+) :: Num a => a -> a -> a Prelude> :t uncurry (+) uncurry (+) :: Num c => (c, c) -> c Prelude> (+) 1 2 3 Prelude> uncurry 1 2 error!! Prelude> uncurry (+) (1, 2) 3
왜냐하면 "무언가(config)와 좌표를 받아 좌표를 반환하는" 함수들을 결합할 경우,
"무언가" 부분을 부여해야 한다는 것이 조합할 때의 표현을 복잡하게 만들기 때문이라고 한다.
// 보다 나은 부품화 function clone(obj) { var f = function(){}; f.prototype = obj; return new f; } // 함수 합성 function compose (f,g) { return function(x) { return f(g(x)); } }; // 병행 이동의 프리미티브 //var trans = function (dx, dy, coord) { // var result = clone(coord); // result.x += dx; // result.y += dy; // return result; //} var trans = function (dx, dy, coord) { return function(coord) { var result = clone(coord); result.x += dx; result.y += dy; return result; } } // 회전 이동의 프리미티브 //var rotate = function (theta, coord) { // var result = clone(coord); // result.x = Math.cos(theta) * coord.x - Math.sin(theta) * coord.y; // result.y = Math.sin(theta) * coord.x + Math.cos(theta) * coord.y; // return result; //} var rotate = function(theta) { return function(coord) { var result = clone(coord); result.x = Math.cos(theta) * coord.x - Math.sin(theta) * coord.y; result.y = Math.sin(theta) * coord.x + Math.cos(theta) * coord.y; return result; } } // 설정을 베이스로 한 병행 이동 //var transByConfig = function (config, coord) { // return trans(config.ofsX, config.ofsY, coord); //} var transByConfig = function(config) { return trans(config.ofsX, config.ofsY); } // 설정을 베이스로 한 회전 //var rotateByConfig = function (config,coord) { // var preTrans = trans(-config.rotAt.x, -config.rotAt.y, coord); // var rotated = rotate(config.theta, preTrans); // var postTrans = trans(config.rotAt.x, config.rotAt.y, rotated); // return postTrans; //} var rotateByConfig = function(config) { return compose(trans(config.rotAt.x, config.rotAt.y), compose(rotate(config.theta), trans(-config.rotAt.x, -config.rotAt.y))); } // 설정을 베이스로 한 좌표 변환 //var convertByConfig = function(config, coord) { // return transByConfig(config, rotateByConfig(config, coord)); //} var convertByConfig = function(config) { return compose(transByConfig(config), rotateByConfig(config)); } var config = { rotAt : { x : 0.5, y : 0.5 } , theta : Math.PI / 4 , ofsX : -0.5 , ofsY : -0.5 } var unit_rect = [ {x:0,y:0}, {x:0,y:1}, {x:1,y:1}, {x:1,y:0} ] // 변환 후의 좌표 //var converted_rect = unit_rect.map(function(coord) { // return convertByConfig(config, coord); //} // 매개변수가 하나로 변하면서 map에서 바로 만들어진 함수를 지정할 수 있다. 하지만 curry를 이용해서 사용할 수도 있겠다. var converted_rect = unit_rect.map(convertByConfig(config)); converted_rect.map(function(coord) { console.log('(' + coord.x.toFixed(6) + ',' + coord.y.toFixed(6)+')'); }함수 안에 있는 알고리즘을 보는 것이 아니라. return을 하는 방식이 변경되었고 compose를 이용한 함수합성을 유심히 봐야한다.
public static void main(String[] args) throws NoSuchAlgorithmException, IOException, KeyManagementException { System.out.println("TLS TEST"); String httpsUrl = "https://stagepg.payletter.com/TLSTest/test.html"; SSLContext sc = SSLContext.getInstance("TLSv1.1"); sc.init(null, null, new java.security.SecureRandom()); URL url = new URL(httpsUrl); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setSSLSocketFactory(sc.getSocketFactory()); BufferedReader br = null; br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "EUC-KR")); String line = ""; while ((line = br.readLine()) != null){ System.out.println(line); } br.close(); }
// 객체 복사용 function clone(obj) { var f = function(){}; f.prototype = obj; return new f; } // 병행 이동의 프리미티브 var trans = function (dx, dy, coord) { var result = clone(coord); result.x += dx; result.y += dy; return result; } var rotate = function (theta, coord) { var result = clone(coord); result.x = Math.cos(theta) * coord.x - Math.sin(theta) * coord.y; result.y = Math.sin(theta) * coord.x + Math.cos(theta) * coord.y; return result; } // 설정을 베이스로 한 병행 이동 var transByConfig = function (config, coord) { return trans(config.ofsX, config.ofsY, coord); } // 설정을 베이스로 한 회전 var rotateByConfig = function (config,coord) { var preTrans = trans(-config.rotAt.x, -config.rotAt.y, coord); var rotated = rotate(config.theta, preTrans); var postTrans = trans(config.rotAt.x, config.rotAt.y, rotated); return postTrans; } // 설정을 베이스로 한 좌표 변환 var convertByConfig = function(config, coord) { return transByConfig(config, rotateByConfig(config, coord)); } var config = { rotAt : { x : 0.5, y : 0.5 } , theta : Math.PI / 4 , ofsX : -0.5 , ofsY : -0.5 } var unit_rect = [ {x:0,y:0}, {x:0,y:1}, {x:1,y:1}, {x:1,y:0} ] // 여기서 coord가 map으로 연결되서서 계속바뀌고 // config는 그대로 계속 공통으로 쓰게 되는 함수를 콜해서 리턴하는 익명함수를 각각 만들어서 실행한다. var converted_rect = unit_rect.map(function(coord) { return convertByConfig(config, coord); }); converted_rect.map(function(coord) { console.log('(' + coord.x.toFixed(6) + ',' + coord.y.toFixed(6)+')'); }); /// curry를 사용하면 좀 더 이뻐 보일 수 있겠다. console.log('===='); var curriedConvertedByConfig = function(coord) { return convertByConfig(config, coord); } var converted_rect2 = unit_rect.map(curriedConvertedByConfig); converted_rect2.map(function(coord) { console.log('(' + coord.x.toFixed(6) + ',' + coord.y.toFixed(6)+')'); });위 내용을 html을 하나 생성해서 로드해보자.
[1] # [] 가 박스의 형태라고 하자. # (어짜피 리스트는 박스의 한 형태이며, 또한 박스처럼 생겼으니 박스라고 하자.)당신은 박스 안에 1을 넣었다. 나중에 시간이 지나서 이 박스 안에 1에 +1을 하고 싶어졌다고 하자.
class Functor f where fmap :: (a -> b) -> f a -> f b
>fmap (+2) [1] [3]나는 [1] 에서 1을 꺼내서 2를 더하지는 못했지만, [1] 박스 안에 (+2) 를 넣어서 박스 안에 값을 3으로 바꾼후 박스에 넣어진 채로 리턴받았다.
(+2) <$> [1] [3]
>[(+2),(+10)] <*> [10,20,30] [12,22,32,20,30,40]앞에 [(+2),(+10)] 는 함수들을 담은 박스다. 이 것을 이용해서 값을 담을 박스 [10,20,30]를 변형시킬 것이다. (아니 변형시키는 것이 아니라 새로 만들어서 리턴하는 것이다.)
> (+) <$> [1,2] <*> [10,20,30] [11,21,31,12,22,32]<$>는 fmap의 infix버전임을 아까 말했다. <*>는 이제 어플리커티브 펑터라고 보자.
Prelude> :info <$> (<$>) :: Functor f => (a -> b) -> f a -> f b -- Defined in ‘Data.Functor’ infixl 4 <$> Prelude> :info <*> class Functor f => Applicative (f :: * -> *) where ... (<*>) :: f (a -> b) -> f a -> f b ... -- Defined in ‘GHC.Base’ infixl 4 <*>infixl 4 <*>, <$> 이 보일 것이다. infix는 중위연산자라는 것이고 그 다음에 붙어있는 l은 left인 것으로 알고 있다. 그러니 left부터 인것이다. (4)는 우선순위이다. 누구먼저 실행되냐인데 둘 다 4 이므로
Prelude> :t (+) <$> [1,2] (+) <$> [1,2] :: Num a => [a -> a]박스 안에 a -> a 가 들어있다. 함수라는 말이다. 아마 [(+1), (+2)] 가 들어있을 것이다. 하지만 볼 수는 없다. Show가 구현되지 않았기 때문이다.
(<*>) = liftA2 id liftA2 f x y = f <$> x <*> yliftA2로 한번 실행해보자.
Prelude> liftA2 (+) [1,2] [10,20,30] [11,21,31,12,22,32]
15 * 1 = 15 (항등원) (15 * 2) * 10 = 15 * (2 * 10) (결합법칙)이런 형태이면 모노이드라고 부르는가 보다.
In category theory, a branch of mathematics, a monad is an endofunctor (a functor mapping a category to itself), together with two natural transformations.여기서는 모나드가 endofunctor라는데 괄호안에 있는 것이 뭘 말하는지는 잘 모르겠다. (functor인데 범주 자신에 매핑된다는 걸보니 아마 이런걸 말하는 가보다. f S -> S, 그러니까 이 박스에서 다른 박스 형태로 매핑되는 것이 아니라.
- In functional programming, a monad is a design pattern that defines how functions, operations, inputs, and outputs can be used together모나드는 함수, 연산자, 인풋, 아웃풋이 제네릭 타입에서 어떻게 이용되는지 '아래와 같은 방식으로' 정의하는 패턴이다.
to build generic types, with the following organization:
1. Define a data type, and how values of that data type are combined.
2. Create functions that use the data type, and compose them together into operations, following the rules defined in the first step.
A monad may encapsulate values of a particular data type, creating a new type associated with a specific additional computation,모나드는 특정 값을 캡슐화 한다. (계산을 하고 박스를 생성해서 거기에 넣는다고 생각해보자.) 일반적으로 특별한 타입을 다룰 때 쓰인다고 한다.
typically to handle special cases of the type. For example, the simple Maybe monad encapsulates variables which may have a null value,
representing an option type, and automatically ensures that null values are not passed as arguments to functions that cannot handle them,
serving as an alternative programming technique to throwing and catching exceptions when null values arise.
Another example is the List monad,또 다른 예제는 List 모나드라고 한다.
where the empty list is a constant value of type List,
and the cons operator binds a plain value as the head of a previous list.
Prelude> :info Monad class Applicative m => Monad (m :: * -> *) where (>>=) :: m a -> (a -> m b) -> m b (>>) :: m a -> m b -> m b return :: a -> m a fail :: String -> m a여기서 (>>=)는 bind라고 불리는 녀석인데 이 녀석이 핵심이다. (>> 이녀석은 then 이었나?) 한번 파헤쳐보자.
(>>=) :: m a -> (a -> m b) -> m b중간에 있는 (m -> m b)를 봐보자. 박스 안에 있는 값을 다루는데 input 값이 m a가 아니라 a 다.
m a >>= (a -> m b)[]를 박스라고 해ㄷ보자.
Prelude> (Just 2) >>= (\x -> return $ x + 2) Just 4 Prelude> (Just 2.0) >>= (\x -> return $ x + 2) Just 4.0보면 알겠지만, 박스 안에 내용을 가져와서 x에 바인딩(그래서 >>=의 이름이 bind인가보다)되어 새로운 박스에 넣어서 리턴한다. 위에 return의 타입을 보자. a를 가져와서 m a를 뱉어낸다. 새로운 박스를 만들어서 뱉어내는 것이다.
package algorithm; import java.util.Arrays; public class Knapsack { static final int MAX_N = 100; static int[][] dp = new int[MAX_N][MAX_N]; static int W; static int[] v; static int[] w; static int n; public static void main(String[] args) { n = 4; w = new int[] {2, 1, 3, 2}; v = new int[] {3, 2, 4, 2}; W = 5; // Arrays.fill(dp, -1); error! for (int[] row : dp) Arrays.fill(row, -1); // int res = solve(0,W); // System.out.println(res); solve2(); } private static int solve(int idx, int weight) { if (dp[idx][weight] >= 0) { return dp[idx][weight]; } int res; if (idx == n) { res = 0; } else if ( weight < w[idx]) { // skip res = solve(idx+1, weight); } else { // 넣는 경우, 넣지 않는 경우. int a = solve(idx + 1, weight); int b = solve(idx + 1, weight - w[idx]) + v[idx]; // 이 경우에만 물건을 넣는 경우 v[idx]로 이때만 추가된다. res = Math.max(a, b); } return dp[idx][weight] = res; } private static void solve2() { // i=idx, j=weight for (int[] row : dp) Arrays.fill(row, 0); // -1이 아님을 주의. 캐시를 하는 것이 아니라. 전부 더할 것이다. for (int i = n - 1; i >= 0; i--) { for (int j = 0; j <= W; j++) { if (j < w[i]) { dp[i][j] = dp[i + 1][j]; } else { dp[i][j] = Math.max(dp[i + 1][j], dp[i + 1][j - w[i]] + v[i]); } } } for (int i = 0; i <= W; i++) { for (int j = 0; j <= W; j++) { System.out.print(dp[i][j] + " "); } System.out.println(); } System.out.println(dp[0][W]); } }
package algorithm; import java.util.Arrays; public class Knapsack { static final int MAX_N = 100; static int[][] dp = new int[MAX_N][MAX_N]; static int W; static int[] v; static int[] w; static int n; public static void main(String[] args) { n = 4; w = new int[] {2, 1, 3, 2}; v = new int[] {3, 2, 4, 2}; W = 5; // Arrays.fill(dp, -1); error! for (int[] row : dp) Arrays.fill(row, -1); int res = solve(0,W); System.out.println(res); } private static int solve(int idx, int weight) { if (dp[idx][weight] >= 0) { return dp[idx][weight]; } int res; if (idx == n) { res = 0; } else if ( weight < w[idx]) { // skip res = solve(idx+1, weight); } else { // 넣는 경우, 넣지 않는 경우. int a = solve(idx + 1, weight); int b = solve(idx + 1, weight - w[idx]) + v[idx]; // 이 경우에만 물건을 넣는 경우 v[idx]로 이때만 추가된다. res = Math.max(a, b); } return dp[idx][weight] = res; } }
/** 동적설계법 01 배낭문제(Knapsack problem) - 0 n = 4 (w, v) = {(2,3),(1,2),(3,4),(2,2)} W = 5 ouput : 7 유명한 배낭 문제이다. 일반적인 방법으로 각 물건에 대해 (넣는다/넣지않는다)로 두 가지 상태로 나눠서 탐색한다. **/ import java.io.*; import java.lang.*; class Main { static int W; static int[] v; static int[] w; static int n; public static void main(String[] args) throws IOException { //BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); n = 4; w = new int[] {2, 1, 3, 2}; v = new int[] {3, 2, 4, 2}; W = 5; int res = solve(0,W); System.out.println(res); } static int solve(int i, int W) { if (i == n) { return 0; } else if ( W < w[i]) { //skip return solve(i+1, W); } else { // 넣지 않는 경우, 넣는 경우 조사. int a = solve(i+1, W); int b = solve(i + 1, W - w[i]) + v[i]; return Math.max(a, b); } } }
// 부분집합 #includevoid print_arr(int arr[], int arr_len) { int i; for (i = 0; i < arr_len; i++) printf("%d ", arr[i]); printf("\n"); } /* 부분집합 공식 P(A) = (e*P(A')) U P(A') e를 포함한 A' 와 e를 포함하지 않는 A'의 합집합 A'는 A' = A - {e} 라고 A에서 집합 {e}를 뺀 것. 그렇지만 코드가 좀 이해가 안된다. */ void subset(int set[], int set_size, int n, int index) { if (index == n) { print_arr(set, set_size); return; } /* set[set_size]가 계속 변경됨. index가 올라감에 따라 set[set_size]의 기존 집합이 덮어씌워진다. ex) set = [0 1 2] 에서 index가 오르면서 set = [0 1] set = [0 2] 뭐 이런식으로... 다른 언어였으면 그냥 set같은 걸 사용하면 좋을 것 같다. */ set[set_size] = index; // set[size_size]로 집합을 흉내. subset(set, set_size+1, n, index+1); // index(e) 포함한 경우. subset(set, set_size, n, index+1); // index(e)를 포함안한 경우. } #define N 100 int main() { int set[N], n; printf("input n : "); scanf("%d", &n); subset(set, 0, n, 0); return 0; }
// Fence Repair p.68 /** 널빤지 N개를 자르려고 한다. 필요한 길이는 L1, L2, L3는 배열로 주어진다. 널빤지 N개의 Ln의 길이로 자르려고 할 때 최소 비용을 구하라. N = 3, L = {8,5,8} 21을 13 과 8로 자르는 비용은 21 13을 5, 8로 자르는 비용 13 총 비용은 34다 탐욕 알고리즘으로 풀 수 있다. - 가장 짧은 널빤지 노드와 그 다음으로 짧은 널빤지의 노드는 형제면 된다. **/ import java.io.*; class Main { public static void main(String[] args) throws IOException { BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int ans = 0, N = 3; int[] L = {8, 5, 8}; // 널빤지가 1개가 될때까지 while (N > 1) { // 가장 짧은 널빤지 mil1, 다음으로 짧은 널빤지 mil2를 구함. int mil1 = 0, mil2 = 1; if (L[mil1] > L[mil2]) { int tmp = mil1; mil1 = mil2; mil2 = tmp; } //3번째 배열부터 또 mil1, mil2보다 작은 것들이 있는지 확인하고 있다면 위치를 갱신한다. for (int i = 2; i < N; i++) { if (L[i] < L[mil1]) { mil2 = mil1; mil1 = i; } else if (L[i] < L[mil2]) { mil2 = i; } } // L[mil1] + L[mil2] 병합 (제일 작은 서로를 합침) int t = L[mil1] + L[mil2]; ans += t; bw.write("ans : " + ans + "\n"); if (mil1 == N - 1) { int tmp = mil1; mil1 = mil2; mil2 = tmp; } L[mil1] = t; // mil1을 합친값을 넣어서 커지게 만든다. (합쳐졌으니.) L[mil2] = L[N-1]; // mil2는 가장 큰 값을 넣는다. (왜지??) N--; } bw.write("ans : " + ans + "\n"); bw.close(); br.close(); }
// 구간 스케줄링 p.59 /** n개의 강의가 있다. 각 강의 시간은 si에서 ti까지다. 가장 많은 강의에 참가하고 싶은 경우, 몇 개의 강의에 참가하는 것이 가능할까? **/ import java.io.*; // import java.util.TreeMap; import java.util.*; class Main { public static void main(String[] args) throws IOException { BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); // BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); final int MAX_N = 100000; // 비교 최대값 int N = 5; int[] S = {1,2,4,6,8}; int[] T = {3,5,7,9,10}; Mapmap = new TreeMap<>(); for(int i = 0; i < N; i++) { map.put(T[i], S[i]); // 종료시간순으로 정렬한다. } int ans = 0; int t = 0; for (int i = 0; i < N; i++) { if (t < map.get(T[i])) { ans++; t = T[i]; bw.write("선택한 강의 : " + (i+1) + "\n"); } } bw.write("ans : " + ans + "\n"); // 출력 3 (1, 3, 5 선택) bw.close(); // br.close(); } public static int min(int a, int b) { if (a > b) return b; else return a; } }
// 코인문제 p.57 /** 1, 5, 10, 50, 100, 500원짜리가 각각 C1, C5, C10, C50, C100, C500개씩 있다. A원을 지불하려면 몇 개의 동전이 있어야 할까. 지불 방법은 적어도 1개는 존재한다고 가정한다. **/ import java.io.*; class Main { public static void main(String[] args) throws IOException { int ans = 0; BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); // BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); final int[] V = {1,5,10,50,100,500}; int[] C = {3,2,1,3,0,2}; int A = 620; // 큰 것부터 넣는다. 탐욕알고리즘 for (int i = 5; i >= 0; i--) { int t = min(A / V[i], C[i]); // A -= t * V[i]; ans += t; } bw.write("ans : " + ans + "\n"); // 출력 6(500x1, 50x2, 5x2 합계 6개) bw.close(); // br.close(); } public static int min(int a, int b) { if (a > b) return b; else return a; } }
strings = input() # number_of_a = len(''.join(x for x in strings if x == 'a')) number_of_a = strings.count('a') n = int(input()) _div, _mod = divmod(n, len(strings)) res = _div * number_of_a for s, m in zip(strings, range(_mod)): if s == 'a': res += 1 print(res)
>>> line = 'asdf fjdk; afed, fjek,asdf, fo' >>> import re >>> re.split(r'[;,\s]\s*', line) ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'fo'] >>> files = re.split(r'(;|,|\s)\s*', line) >>> files ['asdf', ' ', 'fjdk', ';', 'afed', ',', 'fjek', ',', 'asdf', ',', 'fo'] >>> values = files[::2] >>> values ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'fo'] >>> delimiters = files[1::2] >>> delimiters [' ', ';', ',', ',', ','] >>> ''.join(v+d for v,d in zip(values, delimiters)) 'asdf fjdk;afed,fjek,asdf,' >>> re.split(r'(?:,|;|\s)\s*',line) ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'fo']
>>> filename = 'peter.txt' >>> filename.endswith('.txt') True >>> filename.startswith('peter') True >>> choices = ['http:', 'ftp:'] >>> url = 'http://www.python.org' >>> url.startswith(tuple(choices)) >>> re.match('http:|https:|ftp', url) <_sre.SRE_Match object; span=(0, 5), match='http:'>
>>> from fnmatch import fnmatch, fnmatchcase >>> names = ['Dat1.csv', 'Dat2.csv', 'config.ini', 'foo.py'] >>> [name for name in names if fnmatch(name, 'Dat*.csv')] ['Dat1.csv', 'Dat2.csv'] >>> fnmatchcase('foo.txt.','*TXT') False
>>> from fnmatch import fnmatch, fnmatchcase >>> names = ['Dat1.csv', 'Dat2.csv', 'config.ini', 'foo.py'] >>> [name for name in names if fnmatch(name, 'Dat*.csv')] ['Dat1.csv', 'Dat2.csv'] >>> fnmatchcase('foo.txt.','*TXT') False
def factorial(n): if n <= 1: return 1 else: result = 1 for i in range(2, n+1): result *= i return result # nCk = n! / (n-k)! * k! def comb_slow(n, k): return factorial(n) / (factorial(k)*factorial(n-k)) print(comb_slow(6,3)) def comb_fast(n, k): numerator = 1 denominator = 1 k = min(n-k, k) # nCk에서 더 적은 수로 계산하기 위해서. den_list = [] num_list = [] for i in range(k): # 기존 소스에서 이곳을 변경함. denominator *= i + 1 numerator *= n-i den_list.append(i+1) num_list.append(n-i) print('den_list={}'.format('*'.join(str(x) for x in den_list))) print('num_list={}'.format('*'.join(str(x) for x in num_list))) return numerator/denominator print(comb_fast(6,3)) # 번외 중복조합 # nHr = n+r-1Cr def ham(n, k): return comb_fast(n+k-1, k) print(ham(6, 3))# 참고문헌 : https://smlee729.github.io/python/algorithm/2015/03/08/1-nchoosek.html
#include/* 최대이익투자 : 문제로 풀어보는 알고리즘 4 3 투자금액, 투자 가능 기업의 수 2 3 1 기업별 1만원 투자시 이익 4 5 3 기업별 2만원 7 6 7 기업별 3만원 9 8 9 기업별 4만원 return 10 : 최대이익. 4 3 2 3 1 4 5 3 7 6 7 9 8 9 */ #define M 100 #define N 100 int r[M][N]; int max_return[M][N]; void calculate_return(int n, int m) { int i, j, k, max, t; // dynamic programming을 위해 미리 첫번재 기업을 세팅을 한다. (처음이니까 무조건 max) for (i = 0; i <= m; i++) { // 맨 윗줄. max_return[0][i] = r[0][i]; } for (i = 0; i < n; i++) { for (j = 0; j < m+1; j++) { printf("%d ", r[i][j]); } printf("\n"); } // 두번째줄부터 시작함. for (i = 1; i < n; i++) // i는 기업. for (j = 1; j < m+1; j++) { // j는 총 투자할 양 m+1인 이유는 m=0인 경우(투자안한경우)도 다뤄야 하기 때문. // 기업의 수(i) 투자할 양(j)를 작은 수로 시작해서 기록-> 큰 수로 간다. max = -1; for (k = 0; k <= j; k++) { // 이전에 투자한 회사와 액수에 대한 내용을 바탕으로 더한다. // t = 이전 회사에 k를 투자한양과 지금 회사에 j에서 k만큼 이전회사에 투자한 양을 뺀 경우. // 왜 계속 이전회사만하고만 비교를 하냐면 동적프로그래밍으로 계속 그 최대값이 각 배열마다 누적될 것이다. // 그러니 이전 내용과는 비교할 이유가 없다. t = max_return[i-1][k] + r[i][j - k]; // 무조건 왼쪽 + 위쪽인데. //printf("i=%d, j=%d, k=%d t: %d\n", i,j,k,t); if (t > max) max = t; } max_return[i][j] = max; } } int main(void) { int m, n, i, j; scanf("%d %d", &n, &m); for (i = 0; i < n; i++) r[i][0] = 0; for (i = 1; i <= m; i++) for (j = 0; j < n; j++) scanf("%d", &r[j][i]); // 정보를 받아온다. calculate_return(n, m); printf("Max return: %d\n", max_return[n-1][m]); return 0; }
#include#define M 100 #define N 100 int map[M][N]; int max(int x, int y) { if (x > y) return x; return y; } int max_joy(int m, int n) { if (m == 0 && n == 0) { return map[0][0]; } // 맨 위인경우. if (m == 0) { return max_joy(m, n-1) + map[m][n]; } // 맨 왼쪽인경우. if (n == 0) { return max_joy(m-1, n) + map[m][n]; } // 위,왼 중에 max를 골라서 더함. return max(max_joy(m-1, n), max_joy(m, n-1)) + map[m][n]; } int joy[M][N]; void dynamic_joy(int m, int n) { int i, j; joy[0][0] = map[0][0]; // 0,0 처음세팅. // 맨위,맨왼 세팅 for (i = 1; i < m; ++i) { joy[i][0] = joy[i-1][0] + map[i][0]; } for (j = 1; j < n; ++j) { joy[0][j] = joy[0][j-1] + map[0][j]; } // 그 사이들 세팅. for (i = 1; i < m; ++i) for (j = 1; j < n; ++j) joy[i][j] = max(joy[i-1][j], joy[i][j-1]) + map[i][j]; } /* 5 5 1 2 2 1 5 1 4 4 3 1 2 1 1 1 2 1 3 5 1 1 1 5 1 2 2 */ int main() { int m, n, i, j; scanf("%d %d", &m, &n); for (i = 0; i < m; i++) for (j = 0; j < n; j++) scanf("%d", &map[i][j]); printf("%d\n", max_joy(m-1, n-1)); dynamic_joy(m, n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) printf("%d ", joy[i][j]); printf("\n"); } return 0; }
#include출처: 문제로 풀어보는 알고리즘#define M 100 #define N 100 int map[M][N]; long long num_path(int m, int n) { // 장애물이면 0 if (map[m][n] == 0) { return 0; } // m=i,n=j에서 0,0으로 갔으면 +1 if (m == 0 && n == 0) { return 1; } return ((m > 0) ? num_path(m - 1, n) : 0) + ((n > 0) ? num_path(m, n - 1) : 0); } // 와... 값을 리턴하는 것이 아닌 map에 값을 넣는다. long long path[M][N]; void dynamic_programming_path(int m, int n) { int i, j; // 이중포문용 path[0][0] = map[0][0]; // 1. 세로 맨 왼쪽은 왼쪽을 더할필요가 없음. for(i = 1; i < m; ++i) { //i=0 : path[-1][0]이 없기 때문에 스킵 if (map[i][0] == 0) { path[i][0] = 0; } else { path[i][0] = path[i-1][0]; // 2. 여기 path[i][0-1] } } // 2. 가로 맨 왼쪽은 위쪽을 더할 필요가 없음. for(j = 1; j < n; ++j) { // j=0 은 path[0][-1]가 없기 때문에 스킵 if (map[0][j] == 0) { path[0][j] = 0; } else { path[0][j] = path[0][j-1]; // 2. 여기 path[0-1][j] } } for (i = 1; i < m; i++) { for (j = 1; j < n; j++) { if (map[i][j] == 0) { path[i][j] = 0; } else { // 동적프로그래밍 한칸 한칸 나아간다. path[i][j] = path[i-1][j] + path[i][j-1]; } } } } /* 5 5 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 0 1 0 0 1 1 1 */ int main(void) { int m, n, i, j; scanf("%d %d", &m, &n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { scanf("%d", &map[i][j]); } } // 반대로 가는듯. // printf("%lld\n", num_path(m-1, n-1)); dynamic_programming_path(m, n); return 0; }
#include// 수분할 // partition(0, m) =1 // partition(n,m) = i~m partition(n-i,i) int partition(int n, int m) { int count = 0, i; // n/m 수분할은 n/n 수문할과 같으므로 m에 n을 대입한다. // 5를 6까지 이용해서 분할할 수는 없으니까 if (n < m) { // printf("n=%d, m=%d\n", n, m); m = n; } if (n == 0) // Base Case 0 return 1; for (i = 1; i <= m; i++) { // printf("call partition(%d, %d);\n", n-i, i); count += partition(n - i, i); } return count; } #define MAX 1000 int partition_cache(int n, int m) { static int cache[MAX][MAX]; int count = 0, i; if (n < m) { m = n; } if (cache[n][m]) { return cache[n][m]; } if (n == 0) { return cache[n][m] = 1; } for (i = 1; i <= m; i++) { count += partition_cache(n - i, i); } return cache[n][m] = count; } int main(void) { // printf("first %d\n", partition(1000,4)); printf("second %d\n", partition_cache(1000, 4)); return 0; }
#include// 금액 맞추기 // 브루트포스 / 재귀 // 일정금액을 1,2,5,10,20,50 만원으로 계산 가능 가짓수. void brute(int* bills, int money) { int i0, i1, i2, i3, i4; // 각 계산 후 남은 수. int count = 0; for (i0 = money; i0 >= 0; i0 -=bills[0]) for (i1 = i0; i1 >= 0; i1 -= bills[1]) for (i2 = i1; i2 >= 0; i2 -= bills[2]) for (i3 = i2; i3 >= 0; i3 -= bills[3]) for (i4 = i3; i4 >= 0; i4 -= bills[4]) if (i4 % bills[5] == 0) count++; printf("count = %d\n", count); } int better(int* bills, int n, int money) { int count = 0, i; if (n == 1) { if (money % bills[0] == 0) return 1; else return 0; } int len = money / bills[n-1]; for (i = 0; i <= len; i++) { count += better(bills, n-1, money - (bills[n-1] * i)); } return count; } int main(void) { int bills[6] = {1,2,5,10,20,50}; int money = 100; // res = 4562 int numberOfBills = 6; brute(bills, money); // printf("better way : %d\n", better(bills, numberOfBills, money)); return 0; }
#include#include // 피보나치 수열 long long fibo(int n) { if (n == 1 || n == 2) { return 1; } return fibo(n-1) + fibo(n-2); } // cache #define MAXSIZE 100 long long fibo2(int n) { static long long cache[MAXSIZE]; if (cache[n]) return cache[n]; if (n == 1 || n == 2) // cache[n] = 1; return cache[n] = 1; // cache[n] = fibo2(n-1) + fibo2(n-2); return cache[n] = fibo2(n-1) + fibo2(n-2); } // 재귀 없이 풀기 long long fibo3(int n) { int i; long long f_res, f_a, f_b; if (n == 1 || n == 2) return 1; // f(3) = f(2) + f(1); // f(n) = f(n-1) + f(n-2) f_a = 1; f_b = 1; for (i = 3; i <= n; ++i) { f_res = f_a + f_b; f_a = f_b; f_b = f_res; } return f_res; } int main(void) { printf("Hello World\n"); // printf("%lld\n", fibo(100)); printf("%lld\n", fibo2(100)); printf("%lld\n", fibo3(100)); return 0; }
// 이항계수 #include// nCr = n-1Cr-1 + n-1Cr long long binomial_coefficient(int n, int r) { if (r == 0 || r == n) return 1; return binomial_coefficient(n-1, r-1) + binomial_coefficient(n-1, r); } #define MAX_SIZE 100 // cache long long binomial_coefficient2(int n, int r) { static long long cache[MAX_SIZE][MAX_SIZE] = { 0, }; if (cache[n][r]) { return cache[n][r]; } if (r == 0 || r == n) return 1; cache[n][r] = binomial_coefficient2(n-1, r-1) + binomial_coefficient2(n-1, r); return cache[n][r]; } int main(void) { printf("Hello World\n"); //printf("%lld\n", binomial_coefficient(100,52)); // 5C2 printf("%lld\n", binomial_coefficient2(100,52)); // 5C2 return 0; }
#includeint factorial(int n) { int res, i; res = 1; for(i = 2; i <= n; i++) { res *= i; } return res; } int factorial2(int n) { if (n == 1) return 1; return n * factorial2(n - 1); } int main(void) { printf("Hello World\n"); printf("%d\n", factorial(5)); printf("%d\n", factorial2(5)); return 0; }
# property class Square(object): def __init__(self, side): self.side = side def aget(self): return self.side ** 2 def aset(self, value): print('no') def adel(self, value): print('no') area = property(aget, aset, adel, doc='area') # 이게 중요!! s = Square(5) print(s.area)
"""Properties with decorators. 데코레이터를 사용하게 된다. 위에 내용과 같다. """ from __future__ import print_function class Square(object): """A square using properties with decorators. """ def __init__(self, side): self.side = side @property def area(self): """Calculate the area of the square when the attribute is accessed.""" return self.side * self.side @area.setter def area(self, value): """Don't allow setting.""" print("Can't set the area") @area.deleter def area(self): """Don't allow deleting.""" print("Can't delete the area.") if __name__ == '__main__': square = Square(5) print('area:', square.area) print('try to set') square.area = 10 print('area:', square.area) print('try to delete') del square.area print('area:', square.area)
import time import threading class MyThread(threading.Thread): def __init__(self, number, style, *args, **kwargs): super().__init__(*args, **kwargs) self.number = number self.style = style def run(self, *args, **kwargs): print('thread starting') super().run(*args, **kwargs) print('thread has ended') def sleeper(num, style): print('sleeping for {} {}'.format(num, style)) time.sleep(num) t = MyThread(number=3, style='yellow', target=sleeper, args=[3, 'yellow']) t.start()
random_numbers = set() for _ in range(240): res = ''.join(random.choices(string.ascii_uppercase + string.digits, k=10)) random_numbers.add(res) with open('random_number.txt', 'w', newline='\n') as f: [f.write(num+'\n') for num in random_numbers] print(len(random_numbers))
res = ''.join(random.SystemRandom() .choice(string.ascii_uppercase + string.digits) for _ in range(10))이렇게 사용하는게 좋겠다.
#include#include #include "mergesort.h" void printArray(int value[], int count); int main() { int values[] = { 80, 75, 10, 60, 15, 49, 12, 25 }; int count = sizeof(values)/sizeof(int); mergesort(values, count); printArray(values, count); return 0; } void printArray(int value[], int count) { int i = 0; for(i = 0; i < count; i++) { printf("%d ", value[i]); } printf("\n"); }
#ifndef MERGESORT_H_INCLUDED #define MERGESORT_H_INCLUDED void mergesort(int* arr, int count); #endif // MERGESORT_H_INCLUDED
#include#include #include "mergesort.h" void _mergesort(int* arr, int* pBuffer, int start, int end); void _mergesort_division(int* arr, int* pBuffer, int start, int middle, int end); void mergesort(int* arr, int count) { int* pBuffer = (int*)malloc(sizeof(int) * count); if(pBuffer != NULL) { _mergesort(arr, pBuffer, 0, 7); free(pBuffer); } } void _mergesort(int* arr, int* pBuffer, int start, int end) { int middle = 0; if (start < end) { middle = (start + end) / 2; _mergesort(arr, pBuffer, start, middle); _mergesort(arr, pBuffer, middle+1, end); _mergesort_division(arr, pBuffer, start, middle, end); } } void _mergesort_division(int* arr, int* pBuffer, int start, int middle, int end) { int i = 0, j = 0, k = 0, t = 0; i = start; j = middle + 1; k = start; while(i <= middle && j <= end) { if(arr[i] <= arr[j]) { pBuffer[k] = arr[i]; i++; } else { pBuffer[k] = arr[j]; j++; } k++; } if(i <= middle) { for(t = i; t <= middle; t++, k++) { pBuffer[k] = arr[t]; } } else { for(t = j; t <= end; t++, k++) { pBuffer[k] = arr[t]; } } for (t = start; t <= end; t++) { arr[t] = pBuffer[t]; } }
def merge_sort(arr): print('split', arr) if len(arr) > 1: mid = len(arr) // 2 left = arr[:mid] right = arr[mid:] merge_sort(left) merge_sort(right) i, j, k = 0, 0, 0 while i < len(left) and j < len(right): if left[i] < right[j]: arr[k] = left[i] i += 1 else: arr[k] = right[j] j += 1 k += 1 while i < len(left): arr[k] = left[i] i += 1 k += 1 while j < len(right): arr[k] = right[j] j += 1 k += 1 print('merge', a) a = [80, 75, 10, 60, 15, 49, 12, 25] merge_sort(a) print(a)
#include#include #include #include "selection_sort.h" #include "quicksort.h" void printArray(int value[], int count); int main() { int values[] = { 80, 75, 10, 60, 15, 49, 12, 25 }; int count = sizeof(values)/sizeof(int); printf("quicksort\n"); // selection_sort(values, count); quicksort(values, count); printArray(values, count); return 0; } void printArray(int value[], int count) { int i = 0; for(i = 0; i < count; i++) { printf("%d ", value[i]); } printf("\n"); }
#ifndef QUICKSORT_H_INCLUDED #define QUICKSORT_H_INCLUDED void quicksort(int* value, int count); void _quicksort(int* value, int start, int end); int quicksort_division(int* value, int left, int right); void swap(int* left, int* right); #endif // QUICKSORT_H_INCLUDED
#include#include "quicksort.h" void quicksort(int* value, int count) { _quicksort(value, 0, count -1); } void _quicksort(int* value, int start, int end) { int pivot = 0; if (start < end) { pivot = quicksort_division(value, start, end); _quicksort(value, start, pivot - 1); _quicksort(value, pivot+1, end); } } int quicksort_division(int* value, int left, int right) { int pivot = left; while(left = value[pivot]) && (left < right)) right--; if(left < right) { swap(&value[left], &value[right]); } } swap(&value[pivot], &value[right]); return left; } void swap(int* left, int* right) { int temp = *left; *left = *right; *right = temp; }
def quicksort(arr): _quicksort(arr, 0, len(arr)-1) def _quicksort(arr, start, end): if start < end: pivot = _quicksort_division(arr, start, end) _quicksort(arr, start, pivot-1) _quicksort(arr, pivot+1, end) def _quicksort_division(arr, left, right): pivot = left while left < right: while arr[left] < arr[pivot] and left < right: left += 1 while arr[right] >= arr[pivot] and left < right: right -= 1 if left < right: arr[left], arr[right] = arr[right], arr[left] arr[left], arr[pivot] = arr[pivot], arr[left] return left a = [80, 75, 10, 60, 15, 49, 12, 25] quicksort(a)
#!/bin/python3 from itertools import zip_longest s = input().strip() t = input().strip() k = int(input().strip()) output = 0 for idx, (i,j) in enumerate(zip_longest(s, t)): if i is None or j is None or i != j: output = len(s[idx:] + t[idx:]) break if k >= len(s+t): print('Yes') elif k >= output and (k - output) & 1 == 0: print('Yes') else: print('No')
input1 = '1012' number = int(input1) n = len(input1) res = 0 for i in range(n): _in = int(input1[i]) if (_in != 0 and number % _in == 0): res += 1 print(res)
input2 ='1012' number2 = int(input2) a = (int(x) for x in input1) res2 = 0 for i in a: if i != 0 and (number2 % i) == 0: res2 += 1 print(res2)
input3 = '1012' number3 = int(input3) # int_generator = (int(x) for x in input1) res3 = sum( 1 for y in (int(x) for x in input1) if y != 0 and number3 % y == 0) print(res3)