HackerRank MergeSort Counting Inversions


스왑의 횟수를 찾아내는 것이다.

Input

  • 횟수
  • 숫자 리스트 길이
  • 실제 숫자 리스트 (공백으로 구분)

Bubble Sort 솔루션

속도 문제로 Timeout문제를 발생 시킴

def count_inversions(n,a,numSwap=0):
    cumulatedNumSwap = 0
    for i in range(0,n):
        numSwap = 0
        for j in range(0,n-1):
            if a[j] > a[j+1]:
                temp = a[j]
                a[j] = a[j+1]
                a[j+1] = temp
                numSwap += 1
        cumulatedNumSwap += numSwap
        if numSwap == 0:
            break
    return cumulatedNumSwap


t = int(input().strip())
for a0 in range(t):
    n = int(input().strip())
    arr = list(map(int, input().strip().split(' ')))
    numSwap = 0
    numSwap = count_inversions(n,arr,numSwap)
    print(numSwap)
    

출력결과

#input
2
5
1 1 1 2 2
5
2 1 3 1 2

#output
0
4

MergeSort 솔루션

  • MergeSort 자체는 문제가 아니다.
  • Count를 할 때 count += mid - i + 1;이렇게 해야 한다는 점이 가장 어려운 부분이다.
  • 과도하게 문제가 꼬여 있다.
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;

public class Solution {
    
public static long countInversions(int[] arr){
        
        return mergeSort(arr, 0, arr.length - 1);
    }
    
    public static long mergeSort(int[] arr, int start, int end){
        if(start == end)
            return 0;
        int mid = (start + end) / 2;
        long count = 0;
        count += mergeSort(arr, start, mid); //left inversions
        count += mergeSort(arr, mid + 1, end);//right inversions
        count += merge(arr, start, end); // split inversions.
        return count;
    }
    
    public static long merge(int[] arr, int start, int end){
        int mid = (start + end) / 2;
        int[] newArr = new int[end - start + 1];
        int curr = 0;
        int i = start;
        int j = mid + 1;
        long count = 0;
        while(i <= mid && j <=end) {
            if(arr[i] > arr[j]) {
                newArr[curr++] = arr[j++];
                count += mid - i + 1; // Tricky part.
            }
            else
                newArr[curr++] = arr[i++];          
        }
         // Leftover elements here.
        while(i <= mid) {
            newArr[curr++] = arr[i++];    
        }
        
        while(j <= end) {
            newArr[curr++] = arr[j++];
        }
     
        System.arraycopy(newArr, 0, arr, start, end - start + 1); // Usual stuff from merge sort algorithm with arrays.
        return count;
    }
    
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int t = in.nextInt();
        for(int a0 = 0; a0 < t; a0++){
            int n = in.nextInt();
            int arr[] = new int[n];
            for(int arr_i=0; arr_i < n; arr_i++){
                arr[arr_i] = in.nextInt();
            }
            System.out.println(countInversions(arr));
        }
    }
}


'Computer Science > Coding Interview' 카테고리의 다른 글

HackerRank Queues: A Tale of Two Stacks  (0) 2017.07.30
Stacks: Balanced Brackets  (0) 2017.07.30
HackerRank Data Structure  (0) 2017.07.30
Binary Search  (0) 2017.07.28
HackerRank: Basic Problems  (0) 2017.07.25

Binary Search


input = [1,2,3,4,5,6,7,8,9,10]

target = 1
index = 0

min = 0
max = len(input) -1
mid = int(len(input)/2)

step = 1
while (target != input[mid]):
    if input[mid] < target:
        min = mid +1
    else:
        max = mid -1

    mid = int((max+min)/2)
    step +=1

print("target index: %d, steps: %d"%(mid, step))

Points

  • length -1
  • min은 +1
  • max는 -1
    +를 안할 경우 mid값이 변동이 없어서 마지막 위치에 있는 target 값을 못찾는다.
    -를 안할 경우 왼쪽에 있는 값을 step 3번에 찾을 수 있는 것을 4번에 찾는다. int() 때문에 버림이 적용되우 int가 축소 되기 때문에 -를 안해도 지장이 별로 없는 것 같다.


'Computer Science > Coding Interview' 카테고리의 다른 글

HackerRank Queues: A Tale of Two Stacks  (0) 2017.07.30
Stacks: Balanced Brackets  (0) 2017.07.30
HackerRank Data Structure  (0) 2017.07.30
HackerRank MergeSort Counting Inversions  (0) 2017.07.29
HackerRank: Basic Problems  (0) 2017.07.25

HackerRank: Basic Problems


Solution Type

  • Approximate solution
    하나의 정답만 있지 않은 문제를 말한다.
    예를 들면, Image processing이나 computer vision이 이쪽 문제에 해당 한다.

1. Array: Left Rotation

def array_left_rotation_ext(a, n, k):
    for i in range(0,k):
        # change array
        temp = a [0]
        for j in range(0,n):
            if j+1 != n:
                a[j] = a[j+1]
        a[n-1] = temp
    return a
        
def array_left_rotation(a, n, k):
    return a[k:] + a[:k]
    

n, k = map(int, input().strip().split(' '))
a = list(map(int, input().strip().split(' ')))
answer = array_left_rotation(a, n, k);
print(*answer, sep=' ')

첫 번째 함수는 시간이 너무 오래 걸려서 time-out 걸린다.

2. Strings: Making Anagrams

import string


def number_needed(a, b):
    for char in list(string.ascii_lowercase):
        al.append(a.count(char))
        bl.append(b.count(char))
    return sum(abs(x-y) for (x, y) in zip(al, bl))

a = input().strip()
b = input().strip()

al = []
bl = []

print(number_needed(a, b))

Input (stdin)

cde
abc

Your Output (stdout)

4

Expected Output

4

3. Hash Tables: Ransom Note

def ransom_note(magazine, ransom):
    d = {}
    for word in magazine:
        d.setdefault(word, 0)
        d[word] += 1
    
    for word in ransom:
        if word in d:
            d[word] -= 1
        else:
            return False
    return all([x >= 0 for x in d.values()])    

m, n = map(int, input().strip().split(' '))
magazine = input().strip().split(' ')
ransom = input().strip().split(' ')
answer = ransom_note(magazine, ransom)
if(answer):
    print("Yes")
else:
    print("No")

실행결과

6 4
give me one grand today night
give one grand today

Yes
6 5
two times three is not four
two times two is four

No

4. Linked Lists: Detect a Cycle

head point

cycle = true
no cycle = false

"""
Detect a cycle in a linked list. Note that the head pointer may be 'None' if the list is empty.

A Node is defined as: 
 
    class Node(object):
        def __init__(self, data = None, next_node = None):
            self.data = data
            self.next = next_node
"""
def has_cycle(head):
    i = 0
    if head.next == None:
        return False
    
    prev_head = head.next
    next_head = head.next
    
    while next_head != None:
        if i > 100 :
            return True      
        next_head = prev_head.next
        prev_head = next_head
        i += 1
    return False

실행 결과

0
1

5. Sorting: Bubble Sort

n = int(input().strip())
a = list(map(int, input().strip().split(' ')))

cumulatedNumSwap = 0

for i in range(0,n):
    numSwap = 0
    for j in range(0,n-1):
        if a[j] > a[j+1]:
            temp = a[j]
            a[j] = a[j+1]
            a[j+1] = temp
            numSwap += 1
    cumulatedNumSwap += numSwap
    if numSwap == 0:
        break

print("Array is sorted in %d swaps."%cumulatedNumSwap)
print("First Element: %d"%a[0])
print("Last Element: %d"%a[n-1])

In

3
3 2 1

Out

Array is sorted in 3 swaps.
First Element: 1
Last Element: 3

6. Sorting: Comparator

입력값

n // 플레이어 숫자
줄 바꾸고
공백을 두고 플레이어의 이름과 스코어

from functools import cmp_to_key

def cmp_to_key(key):
    return key

class Player:
    def __init__(self, name, score):
        self.name = name
        self.score = score
        
    def comparator(self):
        return(-self.score, self.name)

#--- reference code
n = int(input())
data = []
for i in range(n):
    name, score = input().split()
    score = int(score)
    player = Player(name, score)
    data.append(player)
    
data = sorted(data, key=cmp_to_key(Player.comparator))
for i in data:
    print(i.name, i.score)

input

5
amy 100
david 100
heraldo 50
aakansha 75
aleksa 150

output

aleksa 150
amy 100
david 100
aakansha 75
heraldo 50

7. oddNumbers (smaple test)

l과 r 사이의 숫자에서 odd number만 구해서 list로 반환

# Complete the function below.

def  oddNumbers(l, r):
    oddNumbers=[]
    i = l
    if l % 2 != 0:
        while (i <= r):
            oddNumbers.append(i)
            i+=2
    else:
        i +=1
        while (i<=r):
            oddNumbers.append(i)
            i+=2
    return oddNumbers

실행 결과

3,9
3, 5, 7, 9

8. find number (sample test)

# Complete the function below.

def  findNumber(arr, k):
    for i in arr:
        if i == int(k):
            return "YES"
        else :
            return "NO"

속도 문제가 Fail난다.

def  findNumber(arr, k):
    if k in arr :
        return "YES"
    else :
        return "NO"

속도 문제가 없다.

9. Recursion: Fibonacci Numbers

$$fibonacci(0)=0$$
$$fibonacci(1)=1$$
$$fibonacci(n)=fibonacci(n-1)+fibonacci(n-2)$$

간단한 구현 (단, timeout 걸림)

def fibonacci(n):
    # Write your code here.
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fibonacci(n-1) + fibonacci(n-2)
    
n = int(input())
print(fibonacci(n))

memory 방식: python dictionary 자료구조를 이용해서 처리한다.

memory = {}
def fibonacci(n):
    if n < 2:
        return n
    if not n in memory.keys():
        memory[n] = fibonacci(n-1) + fibonacci(n-2)
    return memory[n]
    
n = int(input())
print(fibonacci(n))

one line lambda code

fibonacci = lambda n:pow(2<<n,n+1,(4<<2*n)-(2<<n)-1)%(2<<n)

10. Bit Manipulation: Lonely Integer

하나만 Unique하게 나타나고 나머진 모두 2번 나타나게 된다.

#!/bin/python3

import sys

def lonely_integer(a):
    uniqueList = [0 for i in range(101)]
    for number in a:
        uniqueList[number] += 1
    
    return uniqueList.index(1)

n = int(input().strip())
a = [int(a_temp) for a_temp in input().strip().split(' ')]
print(lonely_integer(a))

시간 복잡도 O(3n)
공간 복잡도 O(n)

실행결과

# in
1
1
# out
1

# in
9
4 9 95 93 57 4 57 93 9
# out 
95

좀 더 좋은 방법

XOR개념을 이용해서 중복되면 0가 되는 특성을 활용한다.
시간복잡도 O(n)
공간복잡도 O(1)

def lonely_integer(a):
    result = 0
    for i in a:
        result ^= i
    return result

11. Binary Search: Ice Cream Parlor

아이스크림을 사먹는 문제이다.

  • t는 여행 횟수를 의미한다.
    그다음 가각에 대해서 인자가 3개이다.
  • n
  • 각각의 맛에 대한 가격, i 번째가 가격을 의미한다.
t = int(input().strip())
for a0 in range(t):
    m = int(input().strip())
    n = int(input().strip())
    a = list(map(int, input().strip().split(' ')))
 
    # effective cost
    costList = {}
    for i, cost in enumerate(a):
        firUser = cost
        secUser = m - cost
        if secUser in costList.keys():
            print(costList[secUser]+1,i+1)
        else:
            costList[cost] = i

output

# input
2
4
5
1 4 5 3 2
4
4
2 2 4 3


# output
1 4
1 2

해당 문제는 딱히 Binary Search를 사용할 필요가 없다. 그냥 Hash로 사용할 경우 O(n)에 복잡도로 처리가 가능하다.
그저 과거의 cost에 각각의 index를 추가하고 그것에 현재 cost 차액만큼 값이 있는지 확인하면 된다.
ID도 점점 커지므로 딱히 순서를 고려할 필요도 없다.

참고자료
TwoSum


'Computer Science > Coding Interview' 카테고리의 다른 글

HackerRank Queues: A Tale of Two Stacks  (0) 2017.07.30
Stacks: Balanced Brackets  (0) 2017.07.30
HackerRank Data Structure  (0) 2017.07.30
HackerRank MergeSort Counting Inversions  (0) 2017.07.29
Binary Search  (0) 2017.07.28

2017 H-1B Visa petition


H-1B Visa petition 시즌이 4월 3일 시작 된다.


기술 숙련자라면 미국에서 일하기 위한 통로로 가장 사랑하는 루트가 바로 H-1B 비자이다.


2016 작년에만 그것은 85,000+이상의 비자 신청이 당도 했다. 그리고 최종적으로 236,000 petition이 제출 되었다.


일단 $1,225 수수료를 내면 premium processing으로써 H-1B petition이 15일 안에 심사 된다. 만약 lottery에서 선택 된다면 말이다.

그래서 이러한 premium processing의 비율은 59%에 달한다.


non-premium visa petition은 8개월이나 시간이 걸리기 때문이다. 이것은 그들이 승인한 시점으로 처리가 8개월 걸린다는 것이다.


문제는 H-1B 비자가 숙련된 worker에게 할당 되는 것이 아니라는 점이다. 이것은 Big outsourcing firm들에 의해서 남용 되고 있다. 그들이 대부분의 할당양을 채우기 때문이다.


http://money.cnn.com/2017/03/29/technology/h1b-visa-premium-processing/index.html


Complaint #1: Visas aren't given to only the most highly trained workers


Complaint #2: H-1Bs allow employers to import cheap labor


Complaint #3: Startups get the short end of the stick



http://money.cnn.com/2017/02/21/technology/h1b-visa-program-flawed/index.html?iid=EL

리눅스 커널을 vi로 분석하기 위한 태크닉 기술


설정파일


vimrc


2019-01-08 version

vimrc




1. ctags + cscope 설치하기

apt-get install ctags -y
apt-get install cscope -y


TIP: 리눅스 커널의 경우 아키텍쳐를 설정하여 tag를 생성하게 할 수 있음.

스크립트 있는지 확인: "ls -al ./scripts/tags.sh"


2. vim + 플러그인 설치 및 설정하기


http://www.vim.org/scripts/index.php 에서 제공하는 Plugin을 다룬다.


vim 플러그인은 대부분 vundle이라는 plugin manager에 의해서 관리 된다.

이것으로 인해서 plugin 추가 설치 삭제 등이 매우 간편해 졌다.


vim 환경설정 파일만 있어도 필요한 플러그인을 자동으로 검색하여 설치해주기 때문에

작업 컴퓨터의 재구성이 매우 편해졌다.


vim과 git 설치


sudo apt-get install vim -y

sudo apt-get install git -y


디렉터리 생성

mkdir ~/.vim

mkdir ~/.vim/bundle


Plugin Manager Download (vundle)

git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim

# 영문 메뉴얼 사이트가서 매번 최신 link를 확인해 보는 것이 좋음 (2020.1.16일 업데이트 주소)


영문 메뉴얼 사이트: Click


Vundle 사용법 한글 블로그: Click


vi ~/.vimrc 내용 추가



set rtp+=~/.vim/bundle/Vundle.vim

call vundle#begin()


Plugin 'gmarik/Vundle.vim'

Plugin 'The-NERD-Tree' #계층 별로 파일을 보고 접근할 수 있다.

Plugin 'Source-Explorer-srcexpl.vim' 

Plugin 'SrcExpl' #커서가 지시하는 변수들의 정보를 보여줌

Plugin 'taglist.vim' #ctags를 사용하여 소스코드 파일에서 함수, 전역 변수 리스트를 확인할 수 있는 강력한 사이드바를 제공

Plugin 'AutoComplPop' #자동완성 플러긴

Plugin 'snipMate' #for, while과 같은 예약어를 입력할 경우 snip code를 자동으로 제공해 준다. ~/.vim/snippets 에 제공 기준이 있음.

call vundle#end()


 -- 자동완성과 관련된 코드 --
"========== AutoCompletePop ==========
function! InsertTabWrapper()
    let col=col('.')-1
    if !col||getline('.')[col-1]!~'\k'
        return "\<TAB>"
    else
        if pumvisible()
            return "\<C-N>"
        else
            return "\<C-N>\<C-P>"
        end 
    endif
endfunction

inoremap <TAB> <c-r>=InsertTabWrapper()<cr>
hi Pmenu ctermbg=blue
hi PmenuSel ctermbg=yellow ctermbg=black
hi PmenuSbar ctermbg=blue




vim에서 명령 모드 ":" 에서 아래 명령어를 수행

:PluginInstall

#BundleInstall에서 PluginInstall로 명령어가 변경됨.


하단에 Done이 출력 되면 설정한 모든 Plugin이 설치된 것이다.







□ ctags를 이용한 방법

 

ctags의 정의: ctags는 프로그래밍 소스코드에서 태그(전역변수 선언, 함수 정의, 매크로 선언)들의 데이터베이스(tags 파일)를 생성하는 유닉스 명령이다.

 

ctags에서 인식하는 파일 종류

Assembler, ASP, Awk, C, C++, BETA, Cobol, Eiffel, Fortran, Java, Lisp, Lua, Make, Pascal, Perl

PHP, PL/SQL, Python, REXX, Ruby, Scheme, Shell scripts( Bourne/Korn/Z ), S-Lang, Tcl

Vera, Verilog, Vim, VACC/Bison

 

vim에 tags 파일을 등록하는 방법

--단일 지정

:set tags=./tags

--복수 지정

:set tags=./tags,(콤마) 

//매번 해주어도 되고, vimrc에 등록을 해도 된다.

 

 

tj명령은 tag jump의 약자이다. 이 명령어를 실행하면 태크 데이터베이스

파일(tags)에서 start_kernel 태크를 찾아 리스트로 보여주게 된다.

 

:tj start_kernel


창을 분할 해서 오픈 한다.

 

:sts [태크]


스택에 넣었다가 빼면서 이동 한다.


컨트롤 + ] , 컨트롤 + t

 

[ctags 명령 요약]

:ta [태그] or Ctrl+] or :ts[태그] or :tj [태그] //[tag]가 정의된 위치를 나열하고 선택한 위치로 점프, 현재 위치는 스택에 push된다.

:po or Ctrl+t // 스택 top에 저장된 위치를 pop하고 그 위치로 점프

:sts [태그] or :stj [태그] // [태그]가 정의된 위치를 나열하고 선택한 위치로 창을 수평 분할해 새로 생성된 창에 표시

:tn // tj or ts로 점프 했을때 그 선택적으로 점프할 수 있는 목록이 많을 경우 다음 태그로 이동 한다.

:tp // tj or ts로 점프 했을때 그 선택적으로 점프할 수 있는 목록이 많을 경우 이전 태그로 이동 한다.

:tr // tj or ts로 점프 했을때 그 선택적으로 점프할 수 있는 목록이 많을 경우 처음 태그로 이동 한다.

:tl // tj or ts로 점프 했을때 그 선택적으로 점프할 수 있는 목록이 많을 경우 끝 태그로 이동 한다.

 

:pts [태그] // sts랑 매우 유사하지만 커서가 현재 창에 있다.

:ptj [태그] // 미리보기 윈도우에 태그가 정의된 형식을 보여줌. ( 그닥 차이를 못느끼겠다.)

:ptn // ptj나 pts로 점프했을 때 다음 태그로 점프

:ptp // ptj나 pts로 점프했을 때 이전 태그로 점프

:ptr // ptj나 pts로 점프햇을 때 처음 태그로 점프

:ptl // ptj나 pts로 점프했을 때 마지막 태그로 점프

 

 

vim 내장 스크립트 작성

 

홈 디렉터리의 .vimrc 파일을 열어 다음과 같은 행을 추가한다.

 "ctags macro setting
 if version >= 500 // vim 버전이 5.0 이상일 때만 적용하게 만들 었다.
 func! Sts()
       let st = expand("<cword>") // let을 이용해서 st라는 변수를 생성 한다.
          exe "sts ".st // exe를 이용해서 뒤에나온 명령어를 출력 한다. .st를 출력한다.
 endfunc
 nmap ,st :call Sts()<cr> // ,st와 Sts()함수를 매핑 하였다. 
 
 func! Tj()
       let tj = expand("<cword>")
          exe "tj ".tj
 endfunc
 nmap ,tj :call Tj()<cr>
 endif

 


□ CSCOPE를 사용하는 것 

 

ctags로 찾을 수 있는 C, C++ 태그 종류

classes

macro definitions (and # undef names)

enumerators

function definitions

enumeration names

class, struct, or union members

namespaces

function prototypes and declarations [off]

structure names

typedefs

union names

vriable definitions

extern and forward variable declarations [off]

 

위와 같은 종류로는 결국 지역변수나 전역변수가 사용된 곳이나 함수가 사용된 곳을 찾기 힘들다.

 

ctags가 단지 vim이 사용하는 태그 데이터베이스만 만드는 프로그램임에 비해 cscope는 원래부터 C소스를 분석하기 위해 만들어졌다. 그래서 cscope는 vim 없이 자체적으로 동작 가능하며, C 소스를 분석할 때 유용하게 사용할 수 있다.

 

cscope로 분석 가능한 소스 파일에는

Assembly, C, C++, Lex, Yacc등이 있다.

 

이 cscope 또한 심볼 데이터베이스 파일을 만들어야 한다.

 

이것을 매번 입력하기 힘드니 스크립트 파일을 만든다.

mkcscope.sh 파일을 작성 하자.

 

#!/bin/sh
rm -rf cscope.files cscope.files

find . \( -name '*.c' -o -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.s' -o -name '*.S' \) -print > cscope.files

cscope -i cscope.files

 

chmod 755 mkcscope.sh

mv mkcscope.sh /usr/local/bin

 

스크립트 파일을 언제든지 실행 할수 있게 해준다.

 

이제 mkcscope.sh를 실행하면 database를 생성하게 된다.

그 다음 Ctrl+d를 이용해서 빠져 나간다.

 

이제 앞으로 cscope를 사용할 것이라고 vim에게 알려주어야 한다.

=============================================

set csprg=/usr/bin/cscope

set csto=0

set cst

set nocsverb


if filereadable("./cscope.out")

cs add cscope.out

else

cs add /usr/src/linux/cscope.out

endif

set csverb

==============================================



 

-> 사용방법

 

-> cscope 를 실행 하기 위해서는 :cs find {질의종류} {심벌} 을 입력

ex) :cs find s start_kernel

cscope 의 질의 종류

0 or s - > Find this C symbol

1 or g - > Find this definition

2 or d - > Find functions called by this function

3 or c - > Find functions calling this function

4 or t - > Find assignments to

6 or e - > Find this egrep pattern

7 or f - > Find this File

 

 

vim에 스크립트를 등록하자.

 65 func! Css()
 66       let css = expand("<cword>")
 67          new
 68             exe "cs find s ".css
 69                if getline(1) == ""
 70                      exe "q!"
 71                         endif
 72                         endfunc
 73                         nmap ,css :call Css()<cr>
 74
 75                         func! Csc()
 76       let csc = expand("<cword>")
 77          new
 78             exe "cs find c ".csc
 79                if getline(1) == ""
 80                      exe "q!"
 81                         endif
 82                         endfunc
 83                         nmap ,csc :call Csc()<cr>
 84
 85                         func! Csd()
 86       let csd = expand("<cword>")
 87          new
 88             exe "cs find d ".csd
 89                if getline(1) == ""
 90                      exe "q!"
 91                         endif
 92                         endfunc
 93                         nmap ,csd :call Csd()<cr>
 94
 95                         func! Csg()
 96       let csg = expand("<cword>")
 97          new
 98             exe "cs find g ".csg
 99                if getline(1) == ""
100                      exe "q!"
101                         endif
102                         endfunc
103                         nmap ,csg :call Csg()<cr>

 

이렇게 ctags와 cscope를 2개 동시에 사용하면 된다.

일단은 그냥 ctags만 쓰다가 ctags가 찾지 못할 때만 cscope를 쓰자. 왜냐하면 cscope가 더 느리기 때문이다.

즉, 함수나 변수가 사용된 곳을 찾을 때와 같은 경우에만 cscope를 사용하자.

□ vim과 조합하는 기타 기능.

 

http://www.vim.rog/scripts 사이트에서 taglist.vim 스크립트를 받아와 ~/.vim/plugin 디렉토리에 설치한다.


그 다음 명령모드에서 :Tlist를 해보면 스크린샷과 같은 편리한 기능이 나오는것을 볼 수 있다.





vim의 유용한 단축키들


자동완성 기능

Ctrl+p //위로 검색해서 자동완성

Ctrl+n //아래로 검색해서 자동완성

 

해더파일 바로 읽어오기

Ctrl + wf

 

빠른 괄호 탐색 기능

{ }의 부분에서 % 기호를 누른다.

 



git difftool 사용법


git mergetool로 병합을 수행할 시 conflict문제가 발생하면 아래와 같이 해결한다.

git difftool 설정

git config --global diff.tool vimdiff
git config --global difftool.prompt false
git config --global alias.d difftool

vimdiff 사용법

리눅스에서 두 파일을 비교하는 명령어인 vimdiff의 간단한 사용법을 말씀 드리겠습니다.
기본적으로 vimdiff는 vim에서 화면을 분할하고, 두 파일을 열었을 상태와 같다고 보시면 됩니다.
추가적으로 좋은 점은 서로 다른 부분을 표시해주는 부분이죠.
두 파일을 비교하고, 병합하는데 사용할 수 있습니다.

우선 분할된 창에서 다른 창으로 이동하는 명령은 Ctrl + w + w입니다.

차이점이 있는 부분으로 이동하는 명령은 ] + c  [ + c 입니다.
] + c는 현재 위치에서 아래쪽으로 탐색하며,
[ + c는 현재 위치에서 위쪽으로 탐색을 진행합니다.

수정을 원하는 부분을 찾았으면 복사를 해야겠지요.
d + o는 현재 위치에 반대쪽 창의 내용을 복사해 옵니다.
d + p는 현재 위치의 내용을 반대쪽 창에 복사합니다.

vimdiff는 동일한 부분은 생략하여 보여줍니다.
이를 펼치기 위해서는 z + o 또는 z + space를 누르면 됩니다.
반대로 접기 위해서는 z + c를 누르면 됩니다.

마지막으로, 한쪽 창의 내용을 편집하다보면 차이점을 나타내는 표시가 없어질 경우가 있습니다.
이때 :diffupdate를 누르시면 다시 비교하여, 차이점을 표시해 줍니다.

참고 자료

https://www.rosipov.com/blog/use-vimdiff-as-git-mergetool/


Introduction to OpenCL


What is openCL (personal definition)

Low-level language for high-performance heterogeneous data-parallel computation

  • low-level: manual memory management and parallelization. You choose the global dimensions and allocate data
  • Language: a framework with C-like computation kernels. Not really a language
  • High-performance: if your algorithm is a good fit for the hardware E.g., data-parallel
  • Heterogeneous: Code is protable, but perfomrance is not. Different vendors/versions require different optimizations
  • Data-parallel: hardware and software only support data-parallel. Task parallel support is limited on GPUs today.

Why Limited Synchronization?

  • Scales well in hardware
    • Only work-items within a work-group need to communicate
    • GPUs run 32-128 work-gropus(Thread) in parallel

Global Synchronization

  • OpenCL only supoorts global synchronization at the end of a kernel execution

Utility Functions

  • information about each work-item
    • get_global_id(dim)
      • current work-item's ID in a particular dimension

int id = get_global_id(0);
data[id] = sin(data[id]);

- get_work_dim()
	- number of global dimensions in use
- get_global_size(dim)
	- number of global work-items in a particular dimension
- get_local_size(), get_local_id(), get_num_groups(), get_group_id()
	- information about the local dimensions

What do we need to change to use the GPU?

All we have to do is change the CL_DEVICE_TYPE when we get the device to get a_GPU type deivce. The rest of the code will then use the GPU.

Howeverm if we have a complicated kernel while it will run on both the cpu and the gpu you won't get optimal performance.

To get optimal performance, we should modify kernel code along with the number of available cores in the machine.

OpenCL programming model

  • Setup
    • Get the devices (and platform)

    어떤 장치를 사용할지를 선택한다.

    • Create a context (for sharing between devices)

    data 연산을 위해서 어디에서 처리할 지를 선택 하는 것이다.

    • Create command queues (for submitting work)

    선택한 장치에 어떻게 작업을 할당 할지를 선택 한다.
    work을 submit하는 작업을 수행 한다.

  • Compilation
    • Create a program
    • Build the program (compile)
    • Create kernels

    생성된 커널을 command queue에 할당하는 방식을 취한다.

  • Create memory objects
  • Enqueue writes to copy data to the GPU

    데이터를 CPU로부터 복사해서 GPU로 전달하는 작업을 수행 한다.

  • Set the kernel arguments
  • Enqueue kernel executions

    kernel을 command queue로 전달해서 작업을 처리한다.

  • Enqueue reads to copy data back from the GPU
  • Wait for your commands to finish

왜 근데 기다려야 하는가?
이유는 OpenCL은 asynchronous이기 때문이다.
When we enqueue a command we have no idea when it will finish (it's just in the queue.)
By explicitly waiting we make sure it is finished before continuiting.


Python 파라메터 앞에 *와 **의 의미 (*args, **kwargs)


다른사람들이 작성한 python 코드를 보다보면
*args, **kwargs 를 심심치 않게 본다.
그냥 막연하게 "어떤 파라미터를 몇개를 받을지 모르는 경우 사용한다" 라고 알고 있었지만
자세히 설명한 예 가 있어서 소개한다.

*args

  • 파라미터를 몇개를 받을지 모르는 경우 사용한다. args 는 튜플 형태로 전달된다.
def print_param(*args):
    print args
    for p in args:
        print p
 
print_param('a', 'b', 'c', 'd')
#('a', 'b', 'c', 'd')
#a
#b
#c
#d

**kwargs

  • 파라미터 명을 같이 보낼 수 있다. kwargs는 딕셔너리 형태로 전달된다.
def print_param2(**kwargs):
    print kwargs
    print kwargs.keys()
    print kwargs.values()
 
    for name, value in kwargs.items():
        print "%s : %s" % (name, value)
 
print_param2(first = 'a', second = 'b', third = 'c', fourth = 'd')
 
#{'second': 'b', 'fourth': 'd', 'third': 'c', 'first': 'a'}
#['second', 'fourth', 'third', 'first']
#['b', 'd', 'c', 'a']
#second : b
#fourth : d
#third : c
#first : a

그러면 두개를 같이 쓰는 경우는??

def print_param3(*args, **kwargs):
    print args
    print kwargs
 
print_param3('a', 'b')
#('a', 'b')
#{}
 
print_param3(third = 'c', fourth = 'd')
#()
#{'fourth': 'd', 'third': 'c'}
 
print_param3('a', 'b', third = 'c', fourth = 'd')
#('a', 'b')
#{'fourth': 'd', 'third': 'c'}

응용 해 보자

def print_param4(a, b, c):
    print a, b, c
 
p = ['a', 'b', 'c']
print_param4(*p)
#a b c
 
p2 = {'c' : '1', 'a' : '2', 'b' : '3'}
print_param4(**p2)
#2 3 1

출처

http://jhproject.tistory.com/109


GIT tip 정리


충돌 회피

git push 충돌 회피

# git pull시 현재 commit하지 않은 것 때문에 충돌이 발생하면 아래와 같이 stash를 이용해서 임시저장 할 수 있다.
git stash
git stash list
git pull
git stash pop

submodule

가장 처음 실행 했을 때

git submodule update --init --recursive

지속적인 업데이트

git submodule update --recursive

상태 확인

git submodule status

변경 사항 있을 때 강제로 원래대로 돌리기

git submodule update -f --init --recursive

Git stash

branch를 변경할 때 임시로 파일을 저장하는 수단.

# 임시 저장
git stash
# 임시저장 리스트 확인
git stash list
# 임시저장 적용하고 바로 stage 상태로 만듬
git stash apply --index
# 임시저장 제거, hash를 지정하지 않으면 가장 최근 것을 제거함.
git stash drop
# 적용하면서 바로 제거함
git stash pop

파일 삭제

git rm

working directory의 실제 파일을 삭제하는 것이다.
그리고 commit을 해야 한다.

git rm --cached

Staging Area (git index)에서만 제거하고 Working directory에 있는 파일은 지우지 않고 남겨둘 수 있다.
다시 말해서 하드 디스크에 있는 파일은 그대로 두고 Git만 추적하지 않게 한다.

이것은 .gitignore파일에 추가하는것을 빼먹었거나 대용량 로그 파일이나 컴파일된 파일 .a파일 같은 것을 실수로 추가 했을 때 쓴다.

$ git rm --cached readme.txt

#여러게 삭제
$ git rm log/\*.log

rm.txt 파일 생성해서 하기
*명령으로는 이름 매칭이 안될 수도 있다.

  • git status > rm.txt형식으로 list를 만들고 파일명을 다듬은 다음
  • cat rm.txt | xargs git rm --cached으로 해당 txt에 있는것을 staging area에서 제거 한다.

git log

  • checkout 하고 log가 안보이면 git log --all
  • git reflog

특정 파일 변화 로그 찾기

  • git log -p -- ./vta/tutorials/resnet.py
    파일 이름 바뀐것 까지 참조하면서 모두 보이기
  • git log --follow -p --

HEAD detached at

checkoutsha1 hash코드로 하게 되면 자동으로 HEAD가 설정 되지 않는다.
branch 이름으로 할 경우 이런 문제가 발생하지 않지만 그냥 할 경우 발생하게 된다.

commit message를 잃어 버릴 수도 있기 때문에 HEAD 설정을 다시 해주는 것이 좋다.

  • merge를 이용한 방법
    git commit -m "....."
    git branch my-temporary-work
    git checkout master
    git merge my-temporary-work

git diff

기본 설정 포멧

git diff [--options] <commit> <commit> [--] [<path>...]

지금 커밋과 뒤로 두 단계 커밋의 main.c에 대한 비교 커멘드는 아래 3개 모두 동일한 기능을 한다.

$ git diff HEAD^^ HEAD main.c
$ git diff HEAD^^..HEAD -- main.c
$ git diff HEAD~2 HEAD -- main.c

remote하고의 비교

git fetch origin #pull과 다르게 local repo.와 merge하지 않음. 이력만 받아옴.
git diff master origin/master

특정 파일만 보고 싶은 경우

git ls-files | grep .java | xargs git diff

간단히 파일 변화만 보기 --state

$ git diff --stat 2ed6ec *.R

 2018_03_09_NB_SVM_RF_MLP.R       | 314 +++++++++++++++++++++++++++++++
 Class Imbalance.R                |  90 +++++++++
 FeatureSelectionWithRFE.R        |  59 ++++++
 FileWriter.R                     |  93 ++++++++++
 evaluationModel.R                |  38 ++++
 graph.R                          | 188 +++++++++++++++++++
 jsonESLABCollector.R             | 116 ++++++------
 jsonToDataFrame.R                | 385 +++++++++++++++++++++++++++++++++++++++
 jsonToSingleDataFrame.R          | 208 +++++++++++++++++++++
 phone_status_anlysis.R           |  41 ++++-
 post_matchig_with_arrival_time.R | 277 ++++++++++++++++++++++++++++
 refinedAutoLabels.R              | 158 ++++++++++++++++
 12 files changed, 1905 insertions(+), 62 deletions(-)

git 무식하게 완전 초기화

rm -rf .git

git init
git add .
git commit - m "initial commit"

git remote add origin <github-uri>
git push -u --force origin --all

단 위 방법은 submodule이 있을 경우 문제가 발생한다.
그 때는 rebase를 이용해서 정공법으로 해결해야 한다.

Branch 관련

Branch 삭제

#local delete
git branch -d <branch_name>

#remote delete
git push <remote_name> :<branch_name>

Branch 이름 변경

# Local에 있는 branch 이름 변경하기
git branch -m oldbranch newbranch

# Remote에 존재하는 oldbranch 삭제하기
git push origin :oldbranch

# newbranch push 하기
git push origin newbranch

파일 복원

파일 변경 사항 알아내기

특정 파일 변동 사항 검색

git log -- UNLOCKED_Analysis.R

해당 로그 확인

$ git show --stat f27a8d
commit f27a8d01f6fa828d4e38919823fb1ddb462136b6
Author: Jemin Lee <leejaymin@cnu.ac.kr>
Date:   Tue Nov 8 23:50:22 2016 +0900

    change file name

 README.md                                  | 17 +++++++++++++++++
 jsonToDataFrame.R                          |  9 +++++++++
 phone_status_anlysis.R                     |  1 +
 UNLOCKED_Analysis.R => refinedAutoLabels.R |  4 +++-
 4 files changed, 30 insertions(+), 1 deletion(-)

위와 같이 UNLOCKED_Analysis.R파일이 refinedAutoLabels.R로 변경된 것을 알 수 있다.
갑자기 파일이 사라져서 log를 통해서 확인해본 예제이다.

개별파일 원복

git checkout -- <파일> : 워킹트리의 수정된 파일을 index에 있는 것으로 원복
git checkout HEAD -- <파일명> : 워킹트리의 수정된 파일을 HEAD에 있는 것으로 원복(이 경우 --는 생략가능)
git checkout FETCH_HEAD -- <파일명> : 워킹트리의 수정된 파일의 내용을 FETCH_HEAD에 있는 것으로 원복? merge?(이 경우 --는 생략가능)

index 추가 취소

git reset -- <파일명> : 해당 파일을 index에 추가한 것을 취소(unstage). 워킹트리의 변경내용은 보존됨. (--mixed 가 default)
git reset HEAD <파일명> : 위와 동일

특정 commit message에서 복원
$ git checkout ec76bc~1 allData.RData

commit 취소

  • git reset HEAD^ : 최종 커밋을 취소. 워킹트리는 보존됨. (커밋은 했으나 push하지 않은 경우 유용)
  • git reset HEAD~2 : 마지막 2개의 커밋을 취소. 워킹트리는 보존됨.

hard, soft, mixed 차이점

  • git reset --hard HEAD~2
    • 마지막 2개의 커밋을 취소. stage와 워킹트리 모두 원상 복구. 즉 모든 상태가 복구됨.
  • --soft:
    • stage에 올라간 상태로 변경이력이 복구됨
  • --mixed;
    • 워킹트리에만 변경사항이 남아있음. 커밋은 완전 초기화

revert 방식
reset 계열은 결국 커밋을 조작 하기 때문에 혼자 사용하는 branch에서 사용하는것이 적당하다.
여럿이 사용하는 branch라면 revert를 이용해서 이력을 rollback한 내용들도 commit으로 남기는 것이 좋다.

  • git revert HEAD : HEAD에서 변경한 내역을 취소하는 새로운 커밋 발행(undo commit). (커밋을 이미 push 해버린 경우 유용)
    • 취소 커밋 범위 설정 가: git revert [hash1]..[hashN]

워킹트리 전체 원복

git reset --hard HEAD : 워킹트리 전체를 마지막 커밋 상태로 되돌림. 마지막 커밋이후의 워킹트리와 index의 수정사항 모두 사라짐.
(변경을 커밋하지 않았다면 유용)
git checkout HEAD . : ??? 워킹트리의 모든 수정된 파일의 내용을 HEAD로 원복.
git checkout -f : 변경된 파일들을 HEAD로 모두 원복(아직 커밋하지 않은 워킹트리와 index 의 수정사항 모두 사라짐. 신규추가 파일 제외)

* 참조 : reset 옵션

--soft : index 보존, 워킹트리 보존. 즉 모두 보존.
--mixed : index 취소, 워킹트리만 보존 (기본 옵션)
--hard : index 취소, 워킹트리 취소. 즉 모두 취소.

* untracked 파일 제거

git clean -f
git clean -f -d : 디렉토리까지 제거

Git tracked file 용량 파악 하기

git count-objects -vH

100MB 이상 파일 push 하기

100MB이상의 파일을 push 할 경우 아래와 같은 error 메시지를 나타낸다.

remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
remote: error: Trace: a021e64e835a3163bc978f98da55335e
remote: error: See http://git.io/iEPt8g for more information.
remote: error: File huge_files.zip is 151.37 MB; this exceeds GitHubs file size limit of 100.00 MB

large file system (lfs)를 설치하고 이를 이용해서 commit & push를 한다.

brew install git-lfs
git lfs install # you only need to run this once per user account
git lfs track "*.psd" # Git LFS selects the file types you would like.
git add .gitattributes # make sure .gitattributes is tracked.

git add file.psd
git commit -m "Add design file"
git push origin master

트랙킹 파일 리스트 확인: git lfs ls-files

Reference site

민감 파일 이력에서 자동 찾아 제거 (sensitive data remove in entire history)

.gitignore설정을 하지 않아 password와 같은 정보가 들어 있는 config 파일이 commit push 되었을 때 변경이력에서 이러한 부분을 제거하는 방법을 다룬다.

그냥 untacked시키는 방법은 git rm --cached를 사용하면 되나 저장소 history안에 해당 파일 변경 내역이 그대로 남기 때문에 문제는 계속된다.

해결방법으로는
git filter-branchBFG Repo-Cleaner를 이용한 방법 있다.

BFG Repo-Cleaner를 이용한 방법을 다룬다.

java -jar bfg-1.13.0.jar --delete-files <지울 파일 이름>
java -jar bfg-1.13.0.jar --replace-text <지울 파일 이름>
# 원격 저장소에 강제로 반영
git push origin --force --all

Git commit 메시지들 정리하기

Squash all commits (Pull Request 이후에 처리)

git checkout <branch-name>
git rebase -i master # interactive mode
# vim 화면에서 pick이 선택이고 s가 squash 한다는 의미가 된다.
# 그 다음 새로운 commit log를 작성하게 된다.


git push origin branch-name --force

PR이 다수 반영된 upstream 내용을 origin과 local에 반영하기

아래는 여러 방법들 중 하나의 것이다.

git checkout master
git fetch upstream
git rebase upstream/master
git push -f origin master

기존 local branch 삭제

git branch -d <branch name>

참고자료
공식 홈피: https://help.github.com/en/articles/removing-sensitive-data-from-a-repository
BFG: https://rtyley.github.io/bfg-repo-cleaner/

Gitlab, Merge-request fetch 방법

vi ~/.gitconfig
# 추가
[alias]
    mr = !sh -c 'git fetch $1 merge-requests/$2/head:mr-$1-$2 && git checkout mr-$1-$2' -

# fetch and checkout.
# specify mr number in the last
git mr origin 5

또는
git fetch origin merge-requests/58/head:relay_mr

참고자료

참고자료

2.2 Git의 기초 - 수정하고 저장소에 저장하기

Python 2 와 Python 3의 차이점


코드를 유지보수 하다보면 Python2로 작성된 것을 Python3으로 Migration 할 때가 많다.
이 때 생각보다 두 버전간의 backward compatibility를 지원하지 않는 부분이 많다는 것을 알게 된다.
이러한 부분을 다룬다.

xrange vs range

python3는 더이상 xrange를 지원하지 않는다.
무조건 range를 쓴다. 그리고 내부적으로 그형태가 약간 다르므로
xrange를 무조건 range로 대체 할 수도 없다.

python2에서 xrange는 정해진 숫자 만큼 object를 생성한다. 이는 list를 생성하는 range와는 다른 방식이고
looping을 할 때 약간 더 memory efficint 때문에 빠르다. 그래서 python2를 보면 대다수가 xrange를 사용 한다.

python 2    |  python 3
#------------------------
xrange(10)  |  range(10)
range(10)   |  list(range(10))

# example
# python2
[10] + xrange(9)

# python3
[10] + list(range(9))

만약 python3 코드를 python2에서 수행한다면 아래와 같이 입력해주면 된다.

import sys
if sys.version_info < (3,):
    range = xrange

print

python2는 print "string"
python3는 무조건 함수 호출이다. print ("string")

나눗셈

python2는 정수 / 정수 = 졍수 (5/2=2)
python2는 정수 / 정수 = 실수 (5/2=2.5)

생각보다 이런 사소한 문제 때문에 기능이 이상하게 동작 할때가 많다.
자동 타입할당이 편하지만 떄로는 디버깅할 때 상당히 난감하다.


자동으로 commit 위치 찾아서 Git으로 지운 파일 복원하기


버전관리 시스템을 쓰는 이유중 하나가 실수로 지워진 파일을 복원하거나
예전에 필요 없다고 지운 파일을 손쉽게 복원하기 위해서이다.

문제는 commit이 많이 누적 됬다면 해당 파일이 존재하는 위치를 찾는것은 꽤나 귀찮은 일이 된다.
이러한 부분 쉽게 검색으로 해결하는 방법을 다룬다.

특정 경로에 관련된 commit을 찾는 명령어
맨 처음부터 HEAD까지 전부 검색한다는 의미이다.
git rev-list -n 1 HEAD -- <file_path>

git rev-list -n 1 HEAD -- ./0.Basic

f75de024ee267c765d8abfea460ac5f5c506b015

해당 commit 바로 이전으로 checkout하는 방법 caret^을 넣으면 된다.
git checkout <deleting_commit>^ -- <file_path>

git checkout f75de0^ -- ./0.Basic

# 정상적으로 복원됨
jemin@jemin-desktop:~/ESLAB_ML/jemin/TensorFlowLecture$ git status
현재 브랜치 master
브랜치가 'origin/master'에 맞게 업데이트된 상태입니다.
커밋할 변경 사항:
  (스테이지 해제하려면 "git reset HEAD <파일>..."을 사용하십시오)

        새 파일:       0.Basic/Basic_usageOfConstant.py
        새 파일:       0.Basic/Basic_usageOfPlaceholder.py
        새 파일:       0.Basic/Basic_usageOfVariables.py
        새 파일:       0.Basic/TensorFlow Basic of concept.ipynb
        새 파일:       0.Basic/__init__.py
        새 파일:       0.Basic/basic.py
        새 파일:       0.Basic/hellowTensorFlow.py

특정 파일 1개만 하고 싶을 경우
git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file"


Git config 설정 (계정설정)


기본 개념

Git을 설치하고 나면 Git의 사용 환경을 적절하게 설정해 주어야 한다. 한 번만 설정하면 된다. 설정한 내용은 Git을 업그레이드해도 유지된다. 언제든지 다시 바꿀 수 있는 명령어가 있다.

  • git config라는 도구로 설정 내용을 확인하고 변경할 수 있다. Git은 이 설정에 따라 동작한다. 이때 사용하는 설정 파일은 세 가지나 된다.
  • /etc/gitconfig 파일: 시스템의 모든 사용자와 모든 저장소에 적용되는 설정이다. git config --system 옵션으로 이 파일을 읽고 쓸 수 있다.
  • ~/.gitconfig 파일: 특정 사용자에게만 적용되는 설정이다. git config --global 옵션으로 이 파일을 읽고 쓸 수 있다. .git/config: 이 파일은 Git 디렉토리에 있고 특정 저장소(혹은 현재 작업 중인 프로젝트)에만 적용된다. 각 설정은 역순으로 우선시 된다. 그래서 .git/config가 /etc/gitconfig보다 우선한다.

윈도용 Git은 $HOME 디렉토리(%USERPROFILE% 환경변수)에 있는 .gitconfig 파일을 찾는다. 보통 C:\Documents and Settings\$USER 또는 C:\Users\$USER 이다(윈도우에서는 $USER 대신 %USERNAME%를 사용한다). 그리고 msysGit도 /etc/gitconfig를 가지고 있다. 경로는 MSys 루트에 따른 상대 경로다. 인스톨러로 msysGit을 설치할 때 설치 경로를 선택할 수 있다.

계정 설정

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

프로젝트 마다 다른 Email을 사용하고 싶으면 --global 옵션을 제거하면 된다.

설정 확인

$ git config --list
user.name=Scott Chacon
user.email=schacon@gmail.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto


This startup uses batteyr life to determine credit scores


폰의 사용량 예를들면 배터리 소모 같은것들을 이용해서 사용자의 신용도를 평가하는 방식이다.

Singapore에 있는 Lenddo회사이다.
Chairman은 Jeff Stewart 이다.

분석 데이터의 종류

  • smartphone user's messaging
  • browsing activity
  • Wi-Fi network activity

Lenddo puts the data points into a complex proprietary algorithm, which computes how likely someone will default on a loan. Lenders then decide the default rate they want to accept.

While certain mobile behavior could impact the outcome of a credit score (like always running out of battery power), Stewart said extremely well-maintained smartphones raise a red flag in the system, too.

보험 업계에서도 쓰이고 있다.
Your smartphone knows if you're good driver
Even though Lenddo isn't used in the U.S., insurance firms like Liberty Mutual and State Farm have started to adopt similar methodology to help determine car insurance discounts.
For example, the companies have asked customers to submit information collected from their smartphones' GPS, accelerometer and gyroscope to learn how people drive, brake and make turns.

참고문헌

Original Article


몬슨(MONSOON) 파워모니터(Power Monitor)를 이용한 안드로이드 앱 전력 소모 측정 (스마트폰 전력 소모 분석)


본 포스트에서는 학위과정 동안 진행했던 스마트폰 전력 소모 측정을 하는 방법을 다룬다.
스마트폰 전력소모를 측정하는 방법은 여러가지다.
이번에는Monsoon Power Monitor 장비를 이용한 방법으로
가장 쉬운 형태인 분리형 배터리 (removable battery)에 대해서 측정 하는것을 다룬다.

Monsoon Power Monitor의 경우 미국에서 사면 800달러 미만이지만 한국으로 수입해오는 업체를 통해서 구입하면,
120~130만원 정도한다. 나름 개인이 구입하기에는 싼 가격은 아니다.
멀티미터기를 이용한 방법도 이어서 다루도록 하겠다.

준비물

사용된 스마트폰: Galaxy 3
측정 장비: Monsoon Power Monitor, FTA22D
 
테이프: 구리(Copper) tape, 캡톤(Kapton) Tape

측정 실험 환경

간단히 개념화하면 아래와 같은 그림으로 배터리와 폰은 직접적으로 연결 되지 않은 상태이다.
Ground만 연결한 상태에서 Vcc는 Monsoon을 통해서 공급하게 된다.

컴퓨터랑은 USB를 이용해서 연결하므로 그다지 특별한 것은 없다.

실행 화면

단순히 화면을킨 상태에서 외부로부터 카카오톡 메시지를 전송 받을 때의 전력 소모 그래프이다.

해당 그래프는 Galaxy 3는 아니고 Nexus 5로 실험한 것이다.
2011년에 Single core인 Nexus-one으로 연구 진행 했었을 때는 많이 써야 1000mW내외로 소모하던 전력이 Quard-cores로 개발된 Nexus 5의 경우 단순히 Processor와 Wi-Fi 그리고 Display 조금 썻다고 순간적으로 4000mW까지 치솟는걸 보면
현재 스마트폰이 얼마나 배터리를 소모하는 괴물인지 알 수 있다.

이에 맞추어서 Monsoon Power tool v5.0부터는 High Voltage를 허용한다.
원래 Monsoon은 허용 전압이 4.55v였다. 하지만 요즘은 동작 전압이 너무 높기 때문에 이러한 제한을 풀어주는 새로운 버전의Power Tool이 제조사로부터 공급된다.

몬슨의 장점은 전력 소모 측정과 데이터 전송을 동시에 할 수 있다는 점이다.
아래와 같이 USB를 연결한 상태에서 Main channel로 전력을 공급 할 수도 있다.
데이터 전송을 위해서 USB를 활성화 시키면 자동으로 Main channel을 off된다. 
역전류 현상을 방지하기 위함이다.

보통 Multi-meter나 Power supply로 실험 환경을 구성할 경우 데이터 전송을 위해서 USB를 연결하기 어려운 단점이 존재한다.
USB 또한 전류를 공급하기 때문이다.
자동으로 이러한 ON OFF기능이 몬슨의 또하나의 장점이라 할 수 있다.


Github에 100Mb이상 파일 올리는 방법 (오류 해결)


필자의경우 Bitbucket에서 사용하던 Project를 Github로 옴기려고 하다보니 이와 같은 에러가 발생 했다. Github의 경우 개당 파일은 100MB제한이고 있지만 전체 용량 제한은 없다.
Bitbucket은 개당 파일의 제한은 없지만 전체용량이 2GB이상이 안되는 제한사항이 존재 한다.

Github의 경우 50Mb는 Warning을 표시하며, 100Mb부터는 Error를 나타낸다.
따라서 이 이상의 파일을 Push하려하면 아래와 같은 에러를 발생 시킨다.
Github Policy

에러

root@ubuntu:~/python_source/AutoTestingModule# git push github --all
Username: 
Password: 
Counting objects: 40223, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (26581/26581), done.
Writing objects: 100% (40223/40223), 582.06 MiB | 7.94 MiB/s, done.
Total 40223 (delta 12516), reused 40162 (delta 12503)
remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
remote: error: Trace: b052327128727acb5dc9e1fed5cdbb8f
remote: error: See http://git.io/iEPt8g for more information.
remote: error: File TestingResult.tar.gz is 111.47 MB; this exceeds GitHub's file size limit of 100.00 MB
root@ubuntu:~/python_source/AutoTestingModule# git log b05232
fatal: ambiguous argument 'b05232': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions

위 에러 메시지는 HEAD에는 100MB 이상의 파일은 없다.
즉 최근 commit이나 현재 Directory에는 100MB 이상의 파일이 존재하지 않는다. 
하지만 이전 Commit에서라도 100MB이상의 파일이 존재한다면 이러한 에어를 발생 시킨다.
필자의 경우도 TestingResult.tar.gz의 경우 이전에 만들어 두었던 BackUp 파일 하나가 변경이력에 들어가서 문제가된 것이다.

해결방법

경고 메시지에도 나와 있듯이 몇가지 해주면 쉽게 해결이 가능하다.

1.git-lfs 이용

https://git-lfs.github.com/

2. BFG Repo-Cleaner 적용

https://rtyley.github.io/bfg-repo-cleaner/

필자의 경우 그냥 필요없는 파일이라 이전 이력을 뒤져서 제거하는 방법을 선택 했다.
위 공식 사이트에 가서 bfg-x.x.x.jar파일을 다운받고 아래처럼 실행하자.

실행 결과

root@ubuntu:~/python_source/AutoTestingModule# java -jar bfg-1.12.12.jar --strip-blobs-bigger-than 100M

Using repo : /root/python_source/AutoTestingModule/.git

Scanning packfile for large blobs: 40169
Scanning packfile for large blobs completed in 1,435 ms.
Found 1 blob ids for large blobs - biggest=116880364 smallest=116880364
Total size (unpacked)=116880364
Found 36035 objects to protect
Found 7 commit-pointing refs : HEAD, refs/heads/GUI, refs/heads/MultiRun, ...

Protected commits
-----------------

These are your protected commits, and so their contents will NOT be altered:

 * commit 034d2b0b (protected by 'HEAD')

Cleaning
--------

Found 52 commits
Cleaning commits:       100% (52/52)
Cleaning commits completed in 406 ms.

Updating 6 Refs
---------------

    Ref                            Before     After   
    --------------------------------------------------
    refs/heads/GUI               | bfec4c11 | ebffb517
    refs/heads/MultiRun          | 968de654 | d0fd0d5f
    refs/heads/master            | 034d2b0b | abe6ecc0
    refs/remotes/origin/GUI      | bfec4c11 | ebffb517
    refs/remotes/origin/MultiRun | 968de654 | d0fd0d5f
    refs/remotes/origin/master   | 034d2b0b | abe6ecc0

Updating references:    100% (6/6)
...Ref update completed in 262 ms.

Commit Tree-Dirt History
------------------------

    Earliest                                      Latest
    |                                                  |
    ......................DDDDDDDDmmmmmm.mmmmmmmmmmmmmmm

    D = dirty commits (file tree fixed)
    m = modified commits (commit message or parents changed)
    . = clean commits (no changes to file tree)

                            Before     After   
    -------------------------------------------
    First modified commit | 7a6c355c | c9286236
    Last dirty commit     | cb054c2b | 25d98799

Deleted files
-------------

    Filename               Git id             
    ------------------------------------------
    TestingResult.tar.gz | 4153149d (111.5 MB)


In total, 37 object ids were changed. Full details are logged here:

    /root/python_source/AutoTestingModule.bfg-report/2016-08-09/00-21-29

BFG run is complete! When ready, run: git reflog expire --expire=now --all && git gc --prune=now --aggressive


Has the BFG saved you time?  Support the BFG on BountySource:  https://j.mp/fund-bfg

위와 같이 이전 commit에서 빠르게 해당 파일을 찾아서 제거하고 commit메시지를 자동으로 바꾼것을 알 수 있다. 정말 편리한 유틸리티인것 같다.

이제 다시 Github repository에 PUSH를 시도해 보자.

root@ubuntu:~/python_source/AutoTestingModule# git push github --all
Username: 
Password: 
Counting objects: 40223, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (26589/26589), done.
Writing objects: 100% (40223/40223), 471.01 MiB | 8.80 MiB/s, done.
Total 40223 (delta 12516), reused 40126 (delta 12494)
To https://github.com/leejaymin/QDroid.git
 * [new branch]      GUI -> GUI
 * [new branch]      MultiRun -> MultiRun
 * [new branch]      master -> master
root@ubuntu:~/python_source/AutoTestingModule# 

참고문헌


Github Page로 개인 홈페이지 제작, Private Git 얻기


Private 공짜로 얻기

아랴의 링크에서 학생이라면 Github를 약 2년간 공짜로 Private 하게 사용할 수 있다.
지원 할 때는 반드시 University E-mail을 사용해서 지원 해야 한다.
https://education.github.com/pack

목적과 사유를 적어서 보내면 빠르면 2틀 늦어도 15일 이내로 아래와 같은 답장을 받을 수 있다.

목적과 사유는 길게 적을 필요 없다.
필자의 경우 한 3~4줄 영어로 적은것 같다.

GitHub에 로그인해서 Account를 확인해보면 아래와 같은 상태로 변경된 것을 알 수 있다.

2년간 지원해주고 unlimited private repositories를 보장한다.
2년이 지나고 또 메일을 보내면 해주는 것 같다.

Github page 제작

github pages란 static site hosting service를 말한다.

Github pages는 개인홈피, 조직 홈피 또는 project 페이지를 위해서 직접적으로 GitHub repository를 이용해서 디자인 되어 진다.

  • 2016년 6월 이후에 만들어진 page는 github.io domain으로 시작하게 된다.
  • 신용카드 정보 등의 senstive information은 허용하지 않는다.
  • page는 1달에 100,000 요청과 100GB 이하의 트래픽을 허용 한다.
  • 개인 repository의 용량은 1GB 미만을 허용 한다.
  • private repository라도 page자체는 public으로 접근이 가능 하다.

github page의 종류는 크게 두가지 이다.

  • personal page 제작
  • project page 제작

perosnal page 생성 방법

  1. 저장소 생성 반드시 <계정>.github.io 이름으로 생성 한다.

계정이 leejaymin라면, leejaymin.github.io으로 생성 해야한다.
계정 이름은 leejaymin인데 저장소 이름을 jemin.github.io이라고 하면 안된다.
github.io 이것도 전부 저장소 이름 만들때 넣어줘야한다.
당연하겠지만, 이러한 제약으로 인해서 perosnal page는 계정당 1개 뿐이 못만드는것이다.
따라서 project 마다 static web page를 생성하기 위해서는 따른 방법이 존재한다.

  1. 아래의 커맨드를 수행
git clone https://github.com/username/username.github.io
cd username.github.io
~$echo "Hello World" > index.html
git add --all
~$git commit -m "Initial commit"
~$git push -u origin master

http://username.github.io <-- 주소로 접속해보자. 당연히 username은 본인 계정이다.

404 not found같은 것이 뜨면 repository 이름이 잘못된 것이니 수정하면 된다.
setting으로 가서 저장소 이름을 변경하자.

정상적으로 잘 했다면 setting에 아래처럼 주소가 나와야한다.
주의사항을 보면 page는 저장소가 private 이어도 공개된다는 말이 나온다.
개인정보가 유출 되지 않도록 주의 하자.

마크다운으로 html 작업해서 index.html로 commit 후 push하면 심플한 이력 페이지가 된다.
최종 페이지: https://leejaymin.github.io/


나의 경우 보통 아래의 것들을 무시한다.


third party native library의 경우 .so를 무시하면 안된다.


NDK로써 본인이 직접 빌드하는거라면 무시하고 그렇지 않다면 모두 이력을 tracking 해야 한다.


# built application files
*.apk
*.ap_

# files for the dex VM
*.dex

# Java class files
*.class

# built native files (uncomment if you build your own)
# *.o
# *.so

# generated files
bin/
gen/

# Ignore gradle files
.gradle/
build/

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Eclipse Metadata
.metadata/

# Mac OS X clutter
*.DS_Store

# Windows clutter
Thumbs.db

# Intellij IDEA (see https://intellij-support.jetbrains.com/entries/23393067)
.idea/workspace.xml
.idea/tasks.xml
.idea/datasources.xml
.idea/dataSources.ids


만약 build file들이 tracking system에 등록 되었다면 아래의 명령어를 이용해서 제거하자.

해당 명령어는 실제 파일 시스템에서는 제거하지 않고 tracking에서만 제거하는 방법이다.


git rm --cached 


더 쉬운 방법은 모두 제거하고 다시 하는 것이다.


git rm --cached -r . 


.gitignore 파일 생성

git add .






저장소 통채로 복사하기 (bit-bucket to GitHub)


참고자료

git clone --mirror: to clone every references (commit, tags, branches)

git push --mirror: to push everything


git clone --mirror https://bitbucket.org/exampleuser/repository-to-mirror.git

# Make a bare mirrored clone of the repository

cd repository-to-mirror.git

git remote set-url --push origin https://github.com/exampleuser/mirrored

# Set the push location to your mirror

git push --mirror


완전이 제거하고 이동 시키는 방법

// Reference: http://www.blackdogfoundry.com/blog/moving-repository-from-bitbucket-to-github/

// See also: http://www.paulund.co.uk/change-url-of-git-repository

$ cd $HOME/Code/repo-directory

$ git remote rename origin bitbucket

$ git remote add origin https://github.com/mandiwise/awesome-new-repo.git

$ git push origin master

$ git remote rm bitbucket


가장 간단한 방법은 아래와 같이 Github 기능을 이용하는 것이다.

1) Create a new empty repository in GitHub (without readme or licesne, you can add them before) and the following screen will show

2) Inside to import code option you paste your bitbucket URL's repo



우분투 16.04 원격 데스크탑 설정


우분투 to 윈도우

remote desktop 응용프로그램을 그냥 이용 하면 된다. 

윈도우 to 우분투

Ubuntu 16.04
Mate-desktop desktop environment 설치

xrdp 설치

sudo apt-get install xrdp

mate desktop environment
Unity (or Gnome 3)의 desktop드은 xrdp로 잘 동작하지 않는다. 
위 상태로 remote desktop을 설정할 경우 gray screen을 게속해서 보게 된다.

mate-desktop을 설치하면 해결 된다.

sudo apt-get update

sudo apt-get install mate-core mate-desktop-environment mate-notification-daemon

그 외에도 아래의 Desktop environment들이 xrdp를 지원 한다.
xfceLXDELXQTKDE들도 모두 지원 한다.

configuration
xrdp가 설치한 mate를 사용할 수 있도록 해줘야 한다.

이전 버전에서하던 
~/.xsession file을 설정하는 방법은 더이상 동작하지 않는다.

아래의 설정은 mate desktop을 설치 했을 때를 따른다.

/etc/xrdp/startwm.sh 파일을 업데이트 해줘야 한다.

sudo sed -i.bak '/fi/a #xrdp multiple users configuration \n mate-session \n' /etc/xrdp/startwm.sh

이제 윈도우에서 remote desktop으로 연결하면 아래와 같이 정상적으로 연결 된다.

참고자료

http://c-nergy.be/blog/?p=8952


우분투 데스크톱 환경 종류 (uBubtu Deskptop Environment)


기본 Ubuntu는 Unity 데스크톱 환경을 채택 하고 있다. Max OS스타일의 환경으로 이전에 GNOME 기반으로 사용 했던 사람들은 많은 반발을 했었다.

원격데스크톱 xrdp나
VMware Unity Mode도 이 Ubuntu Unity에서는 지원 하지 않는다.

지금 부터 각각의 데스크톱 환경을 알아보자.

logout을 한다음 각각의 데스크톱 환경을 선택하기위해서 
display manager로는 lightdm을 선택 한다.

GNOME Shell

간소화를 최대한 해버린 Desktop enviornment이다.
각 application의 activity들을 쉽게 확인 할 수 있는 장점이 있다.

설치

justin@justin-VM:~$ sudo apt-get install gnome-shell

삭제

sudo apt-get purge gnome-shell
sudo apt-get autoremove
sudo reboot

Unity (installed by default)


기본 우분투 Deskptop environment이다.
2010년 처음 이것을 기본으로 채택 했을 때만 해도 반발이 심했다.
하지만, 최근 16.04에서 부터는 많이 안정화가 되고 속도도 예전처럼 느리지 않다.
Launcher bar도 쉽게 아래로 위치 변경이 가능하다.

설치

sudo apt install ubuntu-desktop

Xfce

가벼움을 지향하는 환경이다.

sudo apt-get install xubuntu-desktop

LXDE (Lightweight X11 Desktop Environment)

진정한 가벼움을 지향 한다.
최소한 리소스 사용을 목표로 한다.

sudo apt-get install lubuntu-desktop

KDE Plasma

Unity 3D를 이용하기 떄문에 그렇게 가볍지는 않다.
이것의 또다른 이름은 Kubuntu이다.

Kubuntu 배포판을 이용해서 설치하는 것이 좋으나, 이미 우분투가 설치되어 있다면 package를 인스톨해서 변경 한다.

Download Kubuntu

sudo apt install kubuntu-desktop

Cinnamon

Gnome-shell desktop을 fork해서 만들어 졌다.

sudo apt-get install cinnamon-desktop-environment

Pantheon

약간 초보자를 위해서 만들어 졌다.

sudo add-apt-repository ppa:elementary-os/daily
# Update and install
sudo apt-get update
sudo apt-get install elementary-desktop

GNOME Flashback/fallback (Ubuntu Classic/GNOME Panel)

2010년 이전에 Ubuntu의 기본 데스크톱 환경이다.
Ubuntu 10.10 이전에 사용됬다. 3D 기능을 사용하지 않으므로 속도가 빠르다.
외관상으로는 큰 변화는 없지만 내부적으로는 많은 개선을 적용 시킨 것이다.

sudo apt-get install update;
sudo apt-get instal gnome-session-flashback

기타 환경들

너무 많기 때문에 아래의 링크를 참조한다.
http://askubuntu.com/questions/65083/what-kinds-of-desktop-environments-and-shells-are-available


VMware에서 Num Lock ON/OFF 무한 반복 문제

계속해서 Num Lock 키가 온오프가 무한 반복 된다면

아래의 방법으로 해결 할 수 있다.

  1. Window + r (실행)
  2. osk 입력 (화상 키보드 실행)
  3. 아래 화며네서 Num Lock 키를 OFF 시킨다.


Amazon Web Services 무료 가입 및 100달러 학생 크래딧 얻기


무료 회원 가입

  1. aws 사이트 오른쪽 상단 가입
    https://aws.amazon.com/ko/

  • 학교 이메일로 가입하는것을 권장
  • 사용 계획은 기본(무료)를 선택
  • 카드 정보 입력하면 $1.00결제가 이뤄지는데 그건 카드 정보 확인용 이므로 취소된다.

  1. 로그인을 하면 오른쪽 상단의 두번째 버튼을 눌러보면 10개의 사용가능한 region이 존재. "seoul"을 선택.

  2. 오른쪽 상단 첫번째 메뉴를 클릭하면 billing management > 기본설정"을 클릭 > 결제 알람 받기 체크

  3. 로그인 > My Account가시면 계정 ID 12자리 숫자가 있다 (AWS Educate 가입시 활용)

AWS Educate 가입 및 활용 방법

https://aws.amazon.com/ko/grants/

연구지원도 있고 교육용도 있다.
연구지원은 따로 Proposal을 작성해야 하므로 학교메일만 있으면 되는 교육용 grant를 받아보자.

  • 학교메일 이용
  • 학교에서 가입하면 (교수 $200 / 학생 $ 100), 지정학교는 PDF로 다운받아서 확인 가능
  • 이메일 인증하고 가입하면 바로 credit code가 전송된다. 이것을 입력해주면 된다.


Doze 변경 사항 (Android 6.0 -> Android 7.0)

Android 6.0에서 이미 Doze를 도입 했었다.

기기가 테이블 위나 서랍 안에 있는 등 유휴 상태일 때 앱이 CPU와 Network를 사용하는 작업을 지연 시키는 방식으로 배터리를 절약하는 시스템 모드를 말한다.

이제 Android N에서 Doze는 한걸음 더 나아가서 이동 중에도 배터리를 절약합니다. 화면이 일정 시간 동안 꺼져있고 기기의 플러그가 뽑혀있으면 Doze는 친숙한 일부 CPU 및 네트워크 제한을 앱에 적용합니다. 즉, 사용자가 기기를 주머니에 휴대하고 다닐 때도 배터리를 절약할 수 있습니다.

https://developer.android.com/preview/behavior-changes.html
https://developer.android.com/training/monitoring-device-state/doze-standby.html#assessing_your_app


Instant Run (Android Studio 2.0)


Google Post: About Instant Run

Android Studio 2.0에 Instant Run이라는 새로운 기능이 추가되었다.
전체를 compile해서 APK를 생성하는것이 아닌 변경된 Dex파일만을 컴파일해서 reload하는 방식이다.
당연히 기존 방법보다 더 빠른 재실행 시간을 보장한다.

사용을 위해서는 다음의 조건을 만족 해야 한다.

  • Android Studio to 2.0 or higher
  • Android Plugin for Gradle vers