반응형

문제링크: https://www.acmicpc.net/problem/1783

 

1783번: 병든 나이트

첫째 줄에 체스판의 세로 길이 N와 가로 길이 M이 주어진다. N과 M은 2,000,000,000보다 작거나 같은 자연수이다.

www.acmicpc.net

 

문제의 규칙입니다.

  1. 2칸 위로, 1칸 오른쪽
  2. 1칸 위로, 2칸 오른쪽
  3. 1칸 아래로, 2칸 오른쪽
  4. 2칸 아래로, 1칸 오른쪽

그리고 4회이상 이동시 4가지이동을 포함해야한다는 규칙이 있습니다.

 

 

만약 n이 1이라면, m값과 관계없이 이동이 불가하기 때문에 1입니다.

 

만약 n이 2이라면, 2번과 3번 이동이 가능해집니다.

올라갔다 내려갔다 하면서 이동할 수 있겠죠! 하지만  4회이상 이동시 4가지이동을 포함해야한다는 규칙때문에 3회의 이동까지만 가능합니다. (1번, 4번이동은 2칸 씩 이동해야하지만 그것이 불가능하기 때문에) 

 

만약 n이 3이상이라면, 규칙적으로 이동하게 됩니다. m이 7이상이여서 문제의 규칙 1, 2, 3, 4번 이동이 모두 가능하다면 각각 4번의 이동를 하고 그 이후부터는 1, 4번 이동만을 반복할 것입니다. (가장 많이 탐색하기 위해서)

즉, m-2번 탐색이 가능해집니다.

 

위의 3가지 규칙을 생각하면서 예외를 처리해주시면 됩니다.

 

정답코드입니다.

 

#include <iostream>
#include <algorithm>
using namespace std;

int n, m;
int main() {
	cin >> n >> m;
	if (n == 1) {
		cout << 1 << endl;
	}
	else if (n == 2) {
		if (m >= 7)
			cout << 4 << endl;
		else
			cout << (m + 1) / 2 << endl;
	}
	else {
		if (m >= 7) {
			cout << m - 2 << endl;
		}
		else {
			cout << min(4, m) << endl;
		}
	}
}

 

n 의 갯수마다 처리해야할 예외가 다릅니다. 

조건문들의 조건은 직접 그림을 그리며 이해해보세요.

화이팅! :)

 

반응형

'알고리즘 > 그리디 알고리즘' 카테고리의 다른 글

[백준] 1092-배(C++)  (0) 2020.05.05
[백준] 10825-국영수(C++)  (0) 2020.03.13
[백준] 8980-택배(C++)  (0) 2020.03.05
[백준] 1969-DNA(C++)  (0) 2020.03.03
[백준] 2437-저울(C++)  (0) 2020.03.03
반응형

문제링크: https://www.acmicpc.net/problem/2352

 

2352번: 반도체 설계

첫째 줄에 정수 n(1 ≤ n ≤ 40,000)이 주어진다. 다음 줄에는 차례로 1번 포트와 연결되어야 하는 포트 번호, 2번 포트와 연결되어야 하는 포트 번호, …, n번 포트와 연결되어야 하는 포트 번호가 주어진다. 이 수들은 1 이상 n 이하이며 서로 같은 수는 없다고 가정하자.

www.acmicpc.net

 

꽤나 애를 먹었습니다.

문제를 읽고 dp문제인 것을 인지했습니다. 

이 문제는 dp알고리즘 중에서도 LIS( Longest Increasing Subsequence) 입니다.

최대 부분 증가 수열이라고도 합니다.

 

 

만약 

10 20 40 30 70 50 60  의 배열이 있을때

 

10 20 30 50 60 이 최대 부분 증가 수열로써 가장 길이가 깁니다.

아래와 같은 뉘앙스로 해결해주면 됩니다.

#include <iostream>
using namespace std;

struct info {
	int count;
	int port_num;
};
int n,result=0;
struct info dp[40001];

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> dp[i].port_num;

	dp[1].count = 1; //초기값 설정

	for (int i = 2; i <= n; i++) {

		for (int j = i - 1; j > 0; j--) {
			if (dp[i].port_num > dp[j].port_num &&dp[i].count < dp[j].count)
				dp[i].count = dp[j].count;
		}
		dp[i].count++;
		if (result < dp[i].count)
			result = dp[i].count;
	}
	cout << result << endl;
}

 
하지만 문제가 생깁니다. 위의 알고리즘은 O(n^2)을 가지게 됩니다.

 

이 문제에서는  n(1 ≤ n ≤ 40,000) 입니다. 즉, 최악의 경우에 O(n^2) = 40000 X 40000 = 1,600,000,000 이 되기 때문에 시간제한 2초로는 어림도 없죠 ( 1억번 연산 당 대략 1초)

 

즉 O(n) or O(nlgn)의 풀이법을 찾아야합니다. 해당 문제에서 이전값들을 비교해서 결과를 도출해야 하기 때문에 O(n)은 불가능합니다.

 

C++ stl에서 제공하는 기능은 1.Lower Bound 2.인덱스 트리 입니다. (정확한 메소드내용은 모르겠지만 탐색시 O(lgn)번의 탐색으로 위치를 전달합니다. 

 

함수들에 관한 자세한 설명은  출처:https://dyngina.tistory.com/16

 

LIS (Longest Increasing Subsequence)

오랫만에 포스팅을 해보네요. 시험기간 (정확히 말하면 시험보는 기간입니다.) 이 되니까 별게 다 하고 싶어지네요. 이번에는 DP중에서 특별히 LIS에 대한 내용을 다뤄보려고 합니다. LIS. Longest Increasing Sub..

dyngina.tistory.com

 

 

제가 만든 정답 코드입니다.

 

#include <iostream>
#include <algorithm>
using namespace std;

int n = 0,len=1;
int arr[40001] ;
int arr2[40001] = { 0 };
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> arr[i];

	arr2[len] = arr[1]; //초기값 설정
	
	for (int i = 2; i <= n; i++) {
		if (arr2[len] < arr[i]) {
			arr2[++len] = arr[i];
		}
		else {
			int val = lower_bound(arr2 + 1, arr2 + len + 1, arr[i]) - arr2;
			arr2[val] = arr[i];
		
		}
		
	}
	
	cout << len << endl;
}

생각해보니 arr는 필요가 없더군요 매번 값을 입력받고 arr2에 저장해주면 됩니다.

그리고 lower_bound메소드의 역할을 이분탐색을 통해서 구현을 할 수 도 있겠군요.

 

 

 

#include <stdio.h>
#define M 40010
int port[M];
int up[M] = { 0x80000001, };
int ref[M];
int n, max;

int search(int left, int right, int x) {
	int mid;

	if (left > right) return left;

	mid = (left + right) / 2;

	if (ref[mid] < x)
		return search(mid + 1, right, x);
	else if (ref[mid] > x)
		return search(left, mid - 1, x);
	else
		return mid;
}

int main() {
	int i, cursor;
	scanf("%d", &n);
	for (i = 1; i <= n; i++) {
		scanf("%d", port + i);
		cursor = search(0, max, port[i]);
		ref[cursor] = port[i];
		up[i] = cursor;
		if (cursor > max)
			max = cursor;
	}
	printf("%d\n", max);
	return 0;
}
반응형
반응형

어려웠습니다...

 

 

우선 첫번째로 고려하셔야 하는게 "문자열의 길이는 1보다 크거나 같고, 1,000,000보다 작거나 같다." 입니다

일반적인 방법으로 문제에 접근하면 "어 그냥 반복해서 문자열을 지워주다가 지울게 없으면 출력하면 되겠네" 겠죠.

 

이때, 최악의 경우 O(n^2)입니다. (n X n/2) 

시간제한범위를 한참 넘습니다. (1억번의 연산당 1초정도입니다.)

1000000 X 1000000/2 = 500000000000 > 200000000

 

 

따라서, 다른방법을 생각해보아야 합니다. 

스택을 사용해야합니다. 

1. 모든 문자열을 스택에 넣는다. 

2. 넣으면서 폭발문자열의 끝 문자와 같다면 스택을 검사합니다.

3. 폭발문자열이 있는지 확인하고, 있다면 해당문자열을 지워줍니다. 

 

 

위 의 방식으로 O(n) 번만에 값을 찾을 수 있습니다.  

 

 

 

 

 

 

두번째로 고려하셔야 할게 있습니다. 

 

저는 string의 erase함수를 사용하며 데이터를 지우면서 결과값을 도출했는데, 45%에서 시간초과가 났습니다. 

  1. C의 strlen
  2. C++의 string.erase
  3. Java의 String.replaceAll
  4. Python의 str.replace, str.find, list.pop(i) etc

굳이 내장함수가 아니더라도 단순히 문자열의 중간을 한 번 지울 때마다 거의 무조건 O(N)이 걸립니다. 즉 지우는 행위를 하면 안됩니다. 

 

 

 

 

 

곰곰히 생각해보니까 해당 스택자체가 결과값이더군요... ( 연결되는 모든 폭발 문자열을 지운 문자열 그자체..)

이거를 늦게 알아서, 고생한 문제 였습니다. 

 

#include <iostream>
#include <string>
using namespace std;

string basic,bomb;
char result[1000001];
int  result_cur = 0;
int main() {
	char lastword;
	cin >> basic;
	cin >> bomb;
	lastword = bomb[bomb.size() - 1];

	for (int i = 0; i < basic.size(); i++) {
		result[result_cur++] = basic[i];
	

		if (basic[i] == lastword) //마지막 문자열과 다르면 스택에 담습니다.
		 { 
			
				bool jud = true;
				for (int j = bomb.size() - 1; j >= 0; j--)
				{
					if (bomb[j] != result[result_cur - 1 - (bomb.size() - 1) + j]) { // 스택의 가장위쪽부터 한칸씩 내려오면서 검사
						jud = false; //즉 해당문자열이 아니면 false
						break;
					}
				}
				if (jud == false) {
					continue;
				}
				else { 
								
					for (int j = 0; j < bomb.size(); j++) {
						result_cur--;				
					}
				}	
		}
	}
	if (result_cur==0)
		cout << "FRULA" << '\n';
	else {
		
		for (int i = 0; i < result_cur; i++) {
			cout << result[i];
		}
		cout << '\n';
	}
}

 

 

result 는 스택, 결과값 입니다. 

 

 

 

 

 

for (int j = bomb.size() - 1; j >= 0; j--)
				{
					if (bomb[j] != result[result_cur - 1 - (bomb.size() - 1) + j]) { // 스택의 가장위쪽부터 한칸씩 내려오면서 검사
						jud = false; //즉 해당문자열이 아니면 false
						break;
					}
				}

3. 폭발문자열이 있는지 확인하고,

 

for (int j = 0; j < bomb.size(); j++) {
						result_cur--;				
					}

 

있다면 해당문자열을 지워줍니다. (스택에서 단순히 커서를 내려줌으로써 지울 수 있겠죠.)

 

 

화이팅:)

 

반응형

'알고리즘 > 문자열 처리' 카테고리의 다른 글

[백준] 2789-유학 금지(C++)  (0) 2020.02.25
[백준] 4949-균형잡힌 세상  (0) 2020.02.24
[백준] 1152-단어의 개수  (0) 2020.02.24
[백준] 1032-명령 프롬프트  (0) 2020.02.24
반응형

너무 쉬워서 설명은 생략입니다

#include <iostream>
#include <string>
using namespace std;
string arr;

int main() {
	cin >> arr;
	for (int i = 0; i < arr.size(); i++)
	{
		if (arr[i] == 'C' || arr[i] == 'A' || arr[i] == 'M' || arr[i] == 'B' || arr[i] == 'R' || arr[i] == 'I' || arr[i] == 'D' || arr[i] == 'G' || arr[i] == 'E'){
			arr.erase(i, 1);
		i--;
		}
	}
	if (arr.size() == 0)
		cout << ' ' << endl;
	else
		cout << arr << endl;
}
반응형

'알고리즘 > 문자열 처리' 카테고리의 다른 글

[백준] 9935-문자열 폭발(C++)  (0) 2020.02.25
[백준] 4949-균형잡힌 세상  (0) 2020.02.24
[백준] 1152-단어의 개수  (0) 2020.02.24
[백준] 1032-명령 프롬프트  (0) 2020.02.24
반응형

문자열에 포함되는 괄호는 소괄호("()") 와 대괄호("[]")로 2종류이고, 문자열이 균형을 이루는 조건은 아래와 같다.

  • 모든 왼쪽 소괄호("(")는 오른쪽 소괄호(")")와만 짝을 이룰 수 있다.
  • 모든 왼쪽 대괄호("[")는 오른쪽 대괄호("]")와만 짝을 이룰 수 있다.
  • 모든 오른쪽 괄호들은 자신과 짝을 이룰 수 있는 왼쪽 괄호가 존재한다.
  • 모든 괄호들의 짝은 1:1 매칭만 가능하다. 즉, 괄호 하나가 둘 이상의 괄호와 짝지어지지 않는다.
  • 짝을 이루는 두 괄호가 있을 때, 그 사이에 있는 문자열도 균형이 잡혀야 한다.

 

 

해당규칙들을 만족시켜야한다. 

즉, '(' 과 ')' 의 개수가 일치하여야 하고 '(' 가 이전에 있어야한다. (대괄호도 마찬가지)

((())) -> yes이고 (())) , ((()) -> no 이다. 

 

 

 

 

짝을 이루는 두 괄호가 있을 때, 그 사이에 있는 문자열도 균형이 잡혀야 한다. 

해당규칙에 따라 ([] [] )(()) ->yes  이고 (([(])) -> no가 된다.

 

 

 

#include <iostream>
#include <string>
using namespace std;

string arr;

int main() {

	while (1) {
		int	stacked[100] = { 0 };
		bool jud = true;
		int small_bracket = 0, big_bracket = 0, stack_index = 0;
		
		getline(cin, arr);
		if (arr[0] == '.'&& arr.size()==1)
			break;

		for (int i = 0; i < arr.size(); i++) {
		
			if (arr[i] == '(') {
				small_bracket++;
				stacked[stack_index++] = 1; // 1이 small 2가 big
			}
			else if (arr[i] == '[') {
				big_bracket++;
				stacked[stack_index++] = 2; // 1이 small 2가 big
			}
			else if (arr[i] == ')') {
				if (small_bracket < 0) {
					jud = false;
					break;
				}
				if (stacked[stack_index-1] != 1) {
					jud = false;
					break;
				}
				else 
					stacked[--stack_index] = 0,small_bracket--;

			}

			else if (arr[i] == ']') {
				if (big_bracket < 0) {
					jud = false;
					break;
				}
				if (stacked[stack_index - 1] != 2) {
					jud = false;
					break;
				}
				else
					stacked[--stack_index] = 0, big_bracket--;

			}

		}

		if (small_bracket != 0 || big_bracket != 0)
			jud = false;

		if (jud == false)
			cout << "no" << endl;
		else
			cout << "yes" << endl;

	}
}
반응형

'알고리즘 > 문자열 처리' 카테고리의 다른 글

[백준] 9935-문자열 폭발(C++)  (0) 2020.02.25
[백준] 2789-유학 금지(C++)  (0) 2020.02.25
[백준] 1152-단어의 개수  (0) 2020.02.24
[백준] 1032-명령 프롬프트  (0) 2020.02.24
반응형

 

전형적인 낚시문제.. 

앞, 뒤에 공백이 있을 수 있다는 사실을 모른채 뉴비들의 정답률을 뺏어간 25퍼짜리 문제입니다..

 

 

쉽습니다.  앞뒤 공백을 제외한 공백의 갯수 + 1이 단어의 개수가 됩니다.

(공백이 연속해서 나오는 경우는 없다. ) 라는 조건 때문입니다. 이것을 고려해서 코드를 짜면 

#include <iostream>
#include <string>
using namespace std;

string arr;
int cnt = 0;
int main() {
	getline(cin,arr);

	for (int i = 0; i < arr.size(); i++)
		if (arr[i] == ' ')
			cnt++;
	if (arr[0] == ' ')
		cnt--;
	if (arr[arr.size() - 1] == ' ')
		cnt--;
	cnt++;
	cout << cnt << endl;

}

이렇게 간단한 코드가 나옵니다.

 

c언어의 strtok이라는 함수를 이용해서 단어를 구분하는 방법도 있습니다. 

 

#include <stdio.h>
#include <string.h>

int main() {
	int count = 0,k=0;
	char arr[1000001];
	gets(arr);
	char *a;
	a = strtok(arr, " ");
	while (a != NULL) {
		count++;
		a = strtok(NULL, " ");
	}
	printf("%d\n", count);
	
}

 

꼭 직접 손으로 짜보시면서 연습하시길 바랍니다. 

반응형

'알고리즘 > 문자열 처리' 카테고리의 다른 글

[백준] 9935-문자열 폭발(C++)  (0) 2020.02.25
[백준] 2789-유학 금지(C++)  (0) 2020.02.25
[백준] 4949-균형잡힌 세상  (0) 2020.02.24
[백준] 1032-명령 프롬프트  (0) 2020.02.24
반응형

정말 쉬운 문자열 처리문제입니다. 

푸는방법도 다양합니다.

 

저는 가장 긴 문자열 기준으로 값을 비교하면서 다른값이거나 문자열이 없다면, ? 

모두 같은 문자라면 해당문자를 추가하는식으로 결과값을 도출했습니다. 

 

 

 

#include <iostream>
#include <string>
using namespace std;

int n = 0;
string arr[50];
string result; 

int main() {
		
	int len = 0,len_index=-1;
	// input 
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> arr[i];
		if (arr[i].size() > len) len = arr[i].size(), len_index = i;
	}

	for (int i = 0; i < len; i++) {
		char word = arr[len_index][i];
		bool jud = false;
		for (int j = 0; j < n; j++) {
			if (i > arr[j].size() - 1) {
				result += '?';
				jud = true;
				break;
			}
			else if(word != arr[j][i]) {
				result += '?';
				jud = true;
				break;
			}
				
		}
		if (jud == false)
			result += word;

	}
	
	cout << result << endl;
}

 

반응형

'알고리즘 > 문자열 처리' 카테고리의 다른 글

[백준] 9935-문자열 폭발(C++)  (0) 2020.02.25
[백준] 2789-유학 금지(C++)  (0) 2020.02.25
[백준] 4949-균형잡힌 세상  (0) 2020.02.24
[백준] 1152-단어의 개수  (0) 2020.02.24
반응형

이번 포스팅에서는 키스토어의 계정을 연동해서 keystore를 이용해서 이더를 송금하는 실습을 진행해보겠습니다.

keystore를 최신으로 업데이트하여야합니다. 우선 전체 코드입니다. 

package com.example.samsungblockchainsdk;
import androidx.appcompat.app.AppCompatActivity;
import com.samsung.android.sdk.blockchain.account.Account;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.Toast;
import com.samsung.android.sdk.blockchain.CoinType;
import com.samsung.android.sdk.blockchain.ListenableFutureTask;
import com.samsung.android.sdk.blockchain.SBlockchain;
import com.samsung.android.sdk.blockchain.account.ethereum.EthereumAccount;
import com.samsung.android.sdk.blockchain.coinservice.CoinNetworkInfo;
import com.samsung.android.sdk.blockchain.coinservice.CoinServiceFactory;
import com.samsung.android.sdk.blockchain.coinservice.ethereum.EthereumService;
import com.samsung.android.sdk.blockchain.exception.HardwareWalletException;
import com.samsung.android.sdk.blockchain.exception.RootSeedChangedException;
import com.samsung.android.sdk.blockchain.network.EthereumNetworkType;
import com.samsung.android.sdk.blockchain.ui.CucumberWebView;
import com.samsung.android.sdk.blockchain.ui.OnSendTransactionListener;
import com.samsung.android.sdk.blockchain.wallet.HardwareWallet;
import com.samsung.android.sdk.blockchain.wallet.HardwareWalletType;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;

public class Main2Activity extends AppCompatActivity implements OnSendTransactionListener {
    Button connect;
    Button generateAccount;
    Button getAccounts;
    Button paymentsheet;
  //  Button sendSmartContract;
    // 웹뷰버튼
    Button webViewInitBtn;


    private SBlockchain sBlockchain ;
    private HardwareWallet wallet;
    private CucumberWebView webView; // 웹뷰 변수 선언
    Account generateAccount1;
    private List<Account> accounts;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        // Blockchain SDK Init
        sBlockchain = new SBlockchain(); // Blockchain SDK Init
        try {
            sBlockchain.initialize(this);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 끝


        //이벤트 리스너 호출 //
        connect = findViewById(R.id.connect);
        generateAccount =  findViewById(R.id.generateAccount);
        getAccounts = findViewById(R.id.getAccounts);
        paymentsheet = findViewById(R.id.paymentsheet);
        //cucumber 이벤트 리스너 호출
        webViewInitBtn = findViewById(R.id.webviewinit); // 웹뷰버튼 객체생성
        webView = findViewById(R.id.cucumber); //큐컴버 웹뷰 객체생성

        connect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getApplicationContext(),"connect버튼이 눌러졌습니다.",Toast.LENGTH_SHORT).show();
                connected();
            }
        });

        generateAccount.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getApplicationContext(),"generateAccount버튼이 눌러졌습니다.",Toast.LENGTH_SHORT).show();
                generate();
            }
        });

        getAccounts.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getApplicationContext(),"getAccounts버튼이 눌러졌습니다.",Toast.LENGTH_SHORT).show();
                setgetAccounts();

            }
        });

      paymentsheet.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              Toast.makeText(getApplicationContext(),"paymentsheet버튼이 눌러졌습니다.",Toast.LENGTH_SHORT).show();
              setPaymentsheet();
          }
      });

      webViewInitBtn.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {

              webViewInit();
          }
      });

        //이벤트 리스너 호출  끝//
    }




    //1. connect
    public void connected(){
       sBlockchain.getHardwareWalletManager()
               .connect(HardwareWalletType.SAMSUNG,true) //하드웨어 wallet을 반환하는 형태입니다.
               .setCallback(new ListenableFutureTask.Callback<HardwareWallet>() { //비동기화  자기혼자 쓰레드로 돌아가기 위해서
                   @Override
                   public void onSuccess(HardwareWallet hardwareWallet) {
                        wallet = hardwareWallet;
                   }

                   @Override
                   public void onFailure(ExecutionException e) {
                       Throwable cause = e.getCause();

                       if (cause instanceof HardwareWalletException) {
                           // handling hardware wallet error
                       } else if (cause instanceof RootSeedChangedException) {
                           // handling root seed changed exception
                       }
                   }

                   @Override
                   public void onCancelled(InterruptedException e) {

                   }
               });
    }




    //2. generateAccount
    private  void generate() { //계정생성
        CoinNetworkInfo coinNetworkInfo = new CoinNetworkInfo(
                CoinType.ETH,
                EthereumNetworkType.ROPSTEN,
                "https://ropsten.infura.io/v3/70ddb1f89ca9421885b6268e847a459d"// 퍼블릭 노드인 공짜인 주소를 가져온거야  + ropsten.infura.io로 들어가서 퍼블릭 노드 불러오기
        );

        sBlockchain.getAccountManager()
                .generateNewAccount(wallet, coinNetworkInfo)
                .setCallback(new ListenableFutureTask.Callback< Account >() {
                    @Override
                    public void onSuccess(Account account) {
                        generateAccount1 = account;
                        Log.e("MyApp", account.toString());
                    }

                    @Override
                    public void onFailure(@NotNull ExecutionException e) {
                        Log.e("MyApp fail",e.toString());

                    }

                    @Override
                    public void onCancelled(@NotNull InterruptedException e) {
                        Log.e("MyApp cancel",e.toString());
                    }
                });

    }



    //3. getAccounts
    private  void setgetAccounts() { //
        accounts = sBlockchain.getAccountManager()
                .getAccounts(wallet.getWalletId(),CoinType.ETH, EthereumNetworkType.ROPSTEN);
        Log.d("MyApp", Arrays.toString(new List[]{accounts})); // 리스트형태로 로그메시지 출력
    }



    //4. paymentsheet
    private  void setPaymentsheet(){ //계정으로 0.01이더만큼 전송합니다.
        CoinNetworkInfo coinNetworkInfo = new CoinNetworkInfo(
                CoinType.ETH,
                EthereumNetworkType.ROPSTEN,
                "https://ropsten.infura.io/v3/70ddb1f89ca9421885b6268e847a459d"// 퍼블릭 노드인 공짜인 주소를 가져온거야  + ropsten.infura.io로 들어가서 퍼블릭 노드 불러오기
        );

        sBlockchain.getAccountManager() //우리 어카운트가 잇겟죠
                .getAccounts(wallet.getWalletId(),
                        CoinType.ETH,
                        EthereumNetworkType.ROPSTEN
                        );
        // 메타마스크와 삼성키스토어의 계좌번호는 서로 다르다. 규칙이 다르기 때문이다.

        EthereumService service = (EthereumService) CoinServiceFactory.getCoinService(this,coinNetworkInfo);
        Intent intent = service
                .createEthereumPaymentSheetActivityIntent(
                        this,
                        wallet,
                        (EthereumAccount) accounts.get(0),
                        "0x94e44C14e7A5863fed31a68AAD9bbc7d30d6A019",
                        new BigInteger("10000000000000000"),
                        null,
                        null
                );
        startActivityForResult(intent,0);


    }
    //5. 웹을 가져오는 실습
    private void webViewInit() {
        CoinNetworkInfo coinNetworkInfo = new CoinNetworkInfo(
                CoinType.ETH,
                EthereumNetworkType.ROPSTEN,
                "https://ropsten.infura.io/v3/70ddb1f89ca9421885b6268e847a459d"
        );
        EthereumService service = (EthereumService) CoinServiceFactory.getCoinService(this, coinNetworkInfo);

        accounts =  sBlockchain.getAccountManager()
                .getAccounts(wallet.getWalletId(), CoinType.ETH, EthereumNetworkType.ROPSTEN);

        webView.init(service, accounts.get(0), this);
        webView.loadUrl("https://faucet.metamask.io/");
    }

    @Override
    public void onSendTransaction(
            @NotNull String requestId,
            @NotNull EthereumAccount fromAccount,
            @NotNull String toAddress,
            @org.jetbrains.annotations.Nullable BigInteger value,
            @org.jetbrains.annotations.Nullable String data,
            @org.jetbrains.annotations.Nullable BigInteger nonce
    ) {
        HardwareWallet wallet =
                sBlockchain.getHardwareWalletManager().getConnectedHardwareWallet();

        Intent intent =
                webView.createEthereumPaymentSheetActivityIntent(
                        this,
                        requestId,
                        wallet,
                        toAddress,
                        value,
                        data,
                        nonce
                );

        startActivityForResult(intent, 0);

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode != 0) {
            return;
        }
        webView.onActivityResult(requestCode, resultCode, data);
    }



}

 

버튼객체선언입니다.

 Button connect;
    Button generateAccount;
    Button getAccounts;
    Button paymentsheet;
    // 웹뷰버튼
    Button webViewInitBtn;

SBlockchain은 1) samsung Blockchain SDK Init을 하고,  2) 하드웨어 wallet을 반환받고, 3) coinNetworkInfo에서 받은 네트워크 정보로 계정을 생성하는데 사용됩니다. 이후 계정에 대한 정보를 해당객체를 통해 얻어옵니다.

wallet은 메소드를 통해 하드웨어 wallet에 대한 정보를 받아와 저장하는 역할입니다. generateAccount1은 계정에 대한 정보를 받아오는 default형 객체이고 List형태로 계정들의 정보를 가져오는 accounts도 선언했습니다. (웹뷰에 관한 내용은 이더송금과는 별개이기에 생략하겠습니다.)

 private SBlockchain sBlockchain ;
    private HardwareWallet wallet;
    private CucumberWebView webView; // 웹뷰 변수 선언
    Account generateAccount1;
    private List<Account> accounts;

SBlockchain의 객체를 초기화합니다.

 // Blockchain SDK Init
        sBlockchain = new SBlockchain(); // Blockchain SDK Init
        try {
            sBlockchain.initialize(this);
        } catch (Exception e) {
            e.printStackTrace();
        }

이벤트 리스너 호출을 위해 객체들을 생성합니다.

 //이벤트 리스너 호출 //
        connect = findViewById(R.id.connect);
        generateAccount =  findViewById(R.id.generateAccount);
        getAccounts = findViewById(R.id.getAccounts);
        paymentsheet = findViewById(R.id.paymentsheet);
        //cucumber 이벤트 리스너 호출
        webViewInitBtn = findViewById(R.id.webviewinit); // 웹뷰버튼 객체생성
        webView = findViewById(R.id.cucumber); //큐컴버 웹뷰 객체생성

이후 각각의 리스너객체에서는 toast메시지를 출력하고 각각에 해당하는 메소드들을 호출하는 구조입니다.

1. connect입니다. 하드웨어 wallet정보를 가져와서 계정과 연결하는 함수입니다. 

//1. connect
    public void connected(){
       sBlockchain.getHardwareWalletManager()
               .connect(HardwareWalletType.SAMSUNG,true) //하드웨어 wallet을 반환하는 형태입니다.
               .setCallback(new ListenableFutureTask.Callback<HardwareWallet>() { //비동기화  자기혼자 쓰레드로 돌아가기 위해서
                   @Override
                   public void onSuccess(HardwareWallet hardwareWallet) {
                        wallet = hardwareWallet;
                   }

                   @Override
                   public void onFailure(ExecutionException e) {
                       Throwable cause = e.getCause();

                       if (cause instanceof HardwareWalletException) {
                           // handling hardware wallet error
                       } else if (cause instanceof RootSeedChangedException) {
                           // handling root seed changed exception
                       }
                   }

                   @Override
                   public void onCancelled(InterruptedException e) {

                   }
               });
    }

2. 네트워크정보를 받습니다. 이때 퍼블릭노드가 필요한데, "https://ropsten.infura.io/" 에 들어가셔서 로그인 하시면 퍼블릭노드를 얻을 수 있습니다. CoinType.ETH, EthereumNetworkType.ROPSTEN로 설정합니다.

해당 네트워크정보와 wallet정보로 계정을 생성합니다. 디버그를 통해 계정의 주소를 알 수 있고 메타마스크에 추가도 할 수 있습니다. 

 

    //2. generateAccount
    private  void generate() { //계정생성
        CoinNetworkInfo coinNetworkInfo = new CoinNetworkInfo(
                CoinType.ETH,
                EthereumNetworkType.ROPSTEN,
                "https://ropsten.infura.io/v3/70ddb1f89ca9421885b6268e847a459d"// 퍼블릭 노드인 공짜인 주소를 가져온거야  + ropsten.infura.io로 들어가서 퍼블릭 노드 불러오기
        );

        sBlockchain.getAccountManager()
                .generateNewAccount(wallet, coinNetworkInfo)
                .setCallback(new ListenableFutureTask.Callback< Account >() {
                    @Override
                    public void onSuccess(Account account) {
                        generateAccount1 = account;
                        Log.e("MyApp", account.toString());
                    }

                    @Override
                    public void onFailure(@NotNull ExecutionException e) {
                        Log.e("MyApp fail",e.toString());

                    }

                    @Override
                    public void onCancelled(@NotNull InterruptedException e) {
                        Log.e("MyApp cancel",e.toString());
                    }
                });

    }

3. 계정들의 정보를 리스트형태로 저장하고 log에 출력하는 구문입니다. 

    //3. getAccounts
    private  void setgetAccounts() { //
        accounts = sBlockchain.getAccountManager()
                .getAccounts(wallet.getWalletId(),CoinType.ETH, EthereumNetworkType.ROPSTEN);
        Log.d("MyApp", Arrays.toString(new List[]{accounts})); // 리스트형태로 로그메시지 출력
    }

 

4. 결제창을 띄우는 코드입니다. 네트워크정보와 어카운트매니저를 불러오고, EthereumService의 객체를 생성해서 인텐트를 구현합니다. 라이브러리에 의해 인텐트되는 것이고 아래 "0x94e44C14e7A5863fed31a68AAD9bbc7d30d6A019"는

보낼 주소 new BigInteger("10000000000000000")는 1wei단위의 이더리움을 의미합니다. 이렇게 하면 0.1이더를 보내는 형태가 될것입니다. 

 

 private  void setPaymentsheet(){ //계정으로 0.01이더만큼 전송합니다.
        CoinNetworkInfo coinNetworkInfo = new CoinNetworkInfo(
                CoinType.ETH,
                EthereumNetworkType.ROPSTEN,
                "https://ropsten.infura.io/v3/70ddb1f89ca9421885b6268e847a459d"// 퍼블릭 노드인 공짜인 주소를 가져온거야  + ropsten.infura.io로 들어가서 퍼블릭 노드 불러오기
        );

        sBlockchain.getAccountManager() //우리 어카운트가 잇겟죠
                .getAccounts(wallet.getWalletId(),
                        CoinType.ETH,
                        EthereumNetworkType.ROPSTEN
                        );
        // 메타마스크와 삼성키스토어의 계좌번호는 서로 다르다. 규칙이 다르기 때문이다.

        EthereumService service = (EthereumService) CoinServiceFactory.getCoinService(this,coinNetworkInfo);
        Intent intent = service
                .createEthereumPaymentSheetActivityIntent(
                        this,
                        wallet,
                        (EthereumAccount) accounts.get(0),
                        "0x94e44C14e7A5863fed31a68AAD9bbc7d30d6A019",
                        new BigInteger("10000000000000000"),
                        null,
                        null
                );
        startActivityForResult(intent,0);


    }

 

5. 웹뷰를 통해서 웹의 화면은 앱으로 보여주는 역할을 합니다. 어렵기도 하지만 하나의 규칙처럼 사용되기도 하고, 복잡하여서 설명을 생략하겠습니다.

 

  //5. 웹을 가져오는 실습
    private void webViewInit() {
        CoinNetworkInfo coinNetworkInfo = new CoinNetworkInfo(
                CoinType.ETH,
                EthereumNetworkType.ROPSTEN,
                "https://ropsten.infura.io/v3/70ddb1f89ca9421885b6268e847a459d"
        );
        EthereumService service = (EthereumService) CoinServiceFactory.getCoinService(this, coinNetworkInfo);

        accounts =  sBlockchain.getAccountManager()
                .getAccounts(wallet.getWalletId(), CoinType.ETH, EthereumNetworkType.ROPSTEN);

        webView.init(service, accounts.get(0), this);
        webView.loadUrl("https://faucet.metamask.io/");
    }

    @Override
    public void onSendTransaction(
            @NotNull String requestId,
            @NotNull EthereumAccount fromAccount,
            @NotNull String toAddress,
            @org.jetbrains.annotations.Nullable BigInteger value,
            @org.jetbrains.annotations.Nullable String data,
            @org.jetbrains.annotations.Nullable BigInteger nonce
    ) {
        HardwareWallet wallet =
                sBlockchain.getHardwareWalletManager().getConnectedHardwareWallet();

        Intent intent =
                webView.createEthereumPaymentSheetActivityIntent(
                        this,
                        requestId,
                        wallet,
                        toAddress,
                        value,
                        data,
                        nonce
                );

        startActivityForResult(intent, 0);

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode != 0) {
            return;
        }
        webView.onActivityResult(requestCode, resultCode, data);
    }

 

다음시간에는 블록체인 sdk 심화과정이 있겠습니다. 

모르시는 부분은 아래 댓글에 남겨주세요. 

반응형

'Blockchain 개발 > SAMSUNG Blockchain SDK' 카테고리의 다른 글

SAMSUNG Blockchain SDK 따라하기(1)  (0) 2020.02.10

+ Recent posts