Data Structures & Algorithms with Javascript : Searching Algorithms
[์ด์ ๊ธ] 2024.07.28 - [๐ค data structures & algorithms] - Data Structures & Algorithms with Javascript : Sorting Algorithms (Advanced) Data Structures & Algorithms with Javascript : Sorting Algorithms (Advanced)2024.07.27 - [๐ค data structures & al
pyotato-dev.tistory.com
๐ฅณ ๋๋์ด Data Structures & Algorithms with JavaScript์ ๋ง์ง๋ง ์ฅ ์ง์ ์ ๋๋ฌํ๋ค.
๋ง์ง๋ง ์ฅ์์๋ dynamic programming (DP)๊ณผ greedy algorithms(ํ์ ์๊ณ ๋ฆฌ์ฆ)์ ๋ํด ๋ค๋ฃฌ๋ค.
DP๋ ๊ฐ๋ ์ฌ๊ท์ ๋ฐ๋๋๋ ๋ฌธ์ ํด๊ฒฐ ๋ฐฉ์์ด๋ผ๊ณ ์ฌ๊ฒจ์ง๋ค.
์ฌ๊ท์ ์ธ ์ ๊ทผ์ ์์์ ์๋๋ก ์์ ๋ฌธ์ ๋ค์ ๋ฌธ์ ๊ฐ ์์ ํ ํด๊ฒฐ๋ ๋๊น์ง ๋ฐ๋ณต์ ์ผ๋ก ํธ๋ ๋ฐ๋ฉด์
DP๋ ์๋์์ ์๋ก ์์ ๋ฌธ์ ๋ค์ ํด๊ฒฐํ๋ฉด ๋ ํฐ ๋ฌธ์ ๋ฅผ ํธ๋ ๋จ์๊ฐ ๋์ด์ ์ด ๋์ ํด๋ค์ ํฉ์ณ์ ํฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ค.
๋ฐ๋ฉด ํ์ ์๊ณ ๋ฆฌ์ฆ์ ํ์ฌ ๊ฐ๋ฅํ ์ต์ ์ ํด๊ฒฐ์ฑ (local optima)์ ์ฐพ์์ ํด๊ฒฐ์ฑ ์ ๋ชจ์ํ๋ค.
์ต์ ์ ๋ต์ ์ฐพ๋ค๋ณด๋ฉด ๊ฒฐ๋ก ์ ์ผ๋ก ์ต์์ ํด๊ฒฐ์ฑ (global optimum)์ ์ฐพ์ ์ ์๋ค๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
ํ์์ด๋ผ๋ ๋ง์ ํ์ฌ ํด๊ฒฐ์ฑ ์ค ๊ฐ์ฅ ์๋ฒฝํ ํด๊ฒฐ์ฑ ์ ๊ณจ๋ผ์ ํด๊ฒฐํ๊ณ ์ ํด์ ์ป์ ์ด๋ฆ์ด๋ค.
์์ง ๋๋ฃจ๋ญ์คํ ๊ฐ๋ ๊ฐ ์๊ณ ๋ฆฌ์ฆ๋ค์ ๋ํด ์์ธํ ์ดํด๋ณด์!
Dynamic Programming
์ฌ๊ท์ ์ผ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ฉด ๊น๋ํ ํ์ด๊ฐ ๊ฐ๋ฅํ์ง๋ง ๋นํจ์จ์ ์ด๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ํฌํจํ ๋ง์ ์ธ์ด๋ค์ ํจ์จ์ ์ผ๋ก ์ฌ๊ทํจ์๋ฅผ ๋ค๋ฃจ์ง ๋ชปํ๋ค.
๋์ DP๋ฅผ ํ์ฉํด ์ฌ๊ท์ ํ์ด๋ฅผ ๋์ฒดํ ์ ์๋ค.
DP๋ ๋ฌธ์ ๋ฅผ ์ชผ๊ฐ ๊ฐ ๊ฒฐ๊ณผ ๊ฐ๋ค์ ์ฃผ๋ก ๋ฐฐ์ด๋ก ๋ ํ๋ก ์ ์ฅํ๋ ๋ฐฉ์์ผ๋ก ํ์ด๋ฅผ ํ๋ค.
DP๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ์์๋ค์ ์ดํด๋ณด์.
ํผ๋ณด๋์น์์ด
ํผ๋ณด๋์น์์ด์ dp๋ก ๊ตฌํ๋ ๋ฐฉ์์ ์ดํด๋ณด์.
๋ค์๊ณผ ๊ฐ์ ์๋ฅผ ํผ๋ณด๋์น ์์ด์ด๋ผ๊ณ ํ๋ค. ์ด์ ๋ ๊ฐ์ ๋ํ ๊ฐ์ด ๋ค์ ๊ฐ์ด ๋๋ ์์ด์ด๋ค.
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55...
์ฌ๊ท์ ์ผ๋ก ํจ์๋ฅผ ๊ตฌํ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
function recurFib(n){
if(n<2){
return n;
} else {
return recurFib(n-1) + recurFib(n-2);
}
}
print(recurFib(10);
์ฌ๊ท์ ์ผ๋ก ํผ๋ณด๋์น์์ด์ ๊ตฌํ๋ ๊ฑด ๋งค์ฐ ๋นํจ์จ์ ์ด๋ค. ๋ค์์ ์ฌ๊ท์ ์ผ๋ก ํผ๋ณด๋์น ์์ด์ ๊ตฌํ ๋ ์์ฑ๋๋ ํธ๋ฆฌ ํํ๋ค.
๊ฐ์ ๊ฐ์ด ์ฌ๋ฌ ๋ฒ ์ฌ์ฐ์ฐ๋์ด์ผ ํ๋ค๋ ๊ฑธ ์ ์ ์๋ค.
์ด๋ฏธ ๊ณ์ฐํ๋ ๊ฐ๋ค์ ์ ์ฅํด์ ์ฌ์ฐ์ฐ์ ํผํ ์ ์๋ค๋ฉด ์ข ๋ ํจ์จ์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ด ๋ ๊ฑฐ ๊ฐ๋ค.
DP์ ๋ ๊ฐ๊น์ด ๋ฐฉ์์ผ๋ก ๊ตฌํํด ๋ณด์.
์ด์ ์ ๋งํ๋ฏ์ด, DP๋ ํด๊ฒฐ ๊ฐ๋ฅํ ๊ฐ์ฅ ๋จ์ํ sub-problem์์ ์์ํด์ ๊ทธ ํด๊ฒฐ์ฑ ์ผ๋ก ๋ ๋ณต์กํ ๋ฌธ์ ๋ค์ ํ์ด๊ฐ๋ฉฐ ์ ๋ต์ ์ฐพ๋ ๋ฐฉ์์ด๋ค.
function dynFib(n) {
let val = []; // ์ค๊ฐ ์ค๊ฐ ๊ฒฐ๊ณผ ๊ฐ์ ์ ์ฅ
for (let i = 0; i <= n; ++i) {
val[i] = 0; // 0๋ถํฐ ์์ํด์
}
if (n == 1 || n == 2) {
return 1; // 1์ด๋ 2๋ฉด 0+1 ์ธ ๊ฒฝ์ฐ์ด๋ฏ๋ก ์ด๋ฅธ ์ข
๋ฃ
}
else {
val[1] = 1;
val[2] = 2;
for (let i = 3; i <= n; ++i) {
val[i] = val[i-1] + val[i-2]; // ์ด์ ๋ ๊ฐ๋ค์ ๋ํด์ค ํ์ฌ ์์น์ ๋ฃ์ด์ค๋ค.
}
return val[n-1];
}
}
์ด์ ํ๋ฒ ๋ ์๊ณ ๋ฆฌ์ฆ๋ค์ ๋ฐํ์ ๋น๊ตํด ๋ณด์. ํ์คํ 20 ์ด์์ ํผ๋ณด๋์น ๊ฐ์ ๊ตฌํ๊ณ ์ ํ ๋ DP๊ฐ ๋ ํจ์จ์ ์ด๋ค.
let start = new Date().getTime();
print(recurFib(20));
let stop = new Date().getTime();
print("recursive time - " + (stop-start) + "milliseconds");
print();
start = new Date().getTime();
print(dynFib(10));
stop = new Date().getTime();
print("dynamic programming time - " + (stop-start) + " milliseconds");
/**
// fib(20)์ธ ๊ฒฝ์ฐ
6765
recursive time - 1milliseconds
55
dynamic programming time - 1 milliseconds
*/
/**
// fib(30)์ธ ๊ฒฝ์ฐ
832040
recursive time - 14milliseconds
55
dynamic programming time - 0 milliseconds
*/
์ค๊ฐ ๊ฐ์ ์ ์ฅํ์ง ์๊ณ ๋ dp์ฒ๋ผ ํจ์จ์ ์ผ๋ก ๋์ํ๋๋ก ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํํ ์๋ ์๋ค.
function iterFib(n) {
let last = 1;
;et nextLast = 1;
;et result = 1;
for (let i = 2; i < n; ++i) {
result = last + nextLast;
nextLast = last;
last = result;
}
return result;
}
๋ฌธ์์ด์ ์ต๋ ๊ณตํต๋ถ๋ถ ๊ตฌํ๊ธฐ
DP๋ฅผ ํ์ฉํด ๋ ๋ฌธ์์ด์ด ๊ณตํต์ ์ผ๋ก ๊ฐ๋ ๋ฌธ์์ด์ ํจ์จ์ ์ผ๋ก ๊ตฌํ ์ ์๋ค.
์๋ฅผ ๋ค์ด, "raven"๊ณผ "havoc"๋ผ๋ ๋ฌธ์์ด๋ค์ด ์์ ๋ ๊ณตํต ๋ฌธ์์ด ์ค ๊ฐ์ฅ ๊ธด ๋ถ๋ถ์ "av"๋ค.
DP๋ก ํ์ดํ๋ ๋ฐฉ์์ ์ดํด๋ณด๊ธฐ ์ ์ brute-force๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ์์ ์ดํด๋ณด์.
A์ B ๋ฌธ์์ด์ด ์๋ค๋ฉด A์ ์ฒซ ์์๋ถํฐ ์์ํด์ B์ ๊ฐ ์์๋ค๊ณผ ๋น๊ตํ์ฌ ๋ค๋ฅธ ๊ฐ์ด ์๊ธฐ๋ฉด A์ ๋ค์ ์์๋ถํฐ B์ ์์๋ค๊ณผ ๋ค์ ๋น๊ตํ๋ฉด์ ์ดํด๋ณด๋ฉด ๋๋ค. for ๋ฃจํ๋ฅผ ๋๋ ํ์๊ฐ ์ด๋ฏธ ๋๋ฌด ๋ง์ ๊ฑฐ๋ผ๊ณ ์์ํ๋ค.
DP๋ ์ด์ฐจ ๋ฐฐ์ด๋ก ์ผ์นํ๋ ๊ฐ์ ๊ฐ์๋ฅผ ์ ์ฅํ์ฌ ๊ณ์ฐํ ์ ์๋ค.
๋จผ์ ์ด์ฐจ์ ๋ฐฐ์ด์ ๋ชจ๋ ๊ฐ์ 0์ผ๋ก ์ด๊ธฐํํ๋ค.
๊ฐ์ ๊ฐ์ด ๋ฐ๊ฒฌ๋ ๋๋ง๋ค ๊ฐ ํ๋ ฌ์ ๊ฐ์ 1์ฉ ์ฆ๊ฐ์์ผ ์ค๋ค.
// ์ด๊ธฐํ
a b b c c
d 0 0 0 0 0
b 0 0 0 0 0
b 0 0 0 0 0
c 0 0 0 0 0
c 0 0 0 0 0
a b b c c
d 0 0 0 0 0
b 0 1 1 0 0
b 0 1 2 0 0
c 0 0 0 3 1
c 0 0 0 1 4
์ด์ ์ฝ๋๋ก ์ฎ๊ฒจ๋ณด์!
const print = item => console.log(item);
function lcs(word1, word2){
let max = 0;
let index = 0;
let lcsarr = Array.from(word1,(v,i)=>Array.from(word2,()=>0)); // ์ด์ฐจ์ ๋ฐฐ์ด 0์ผ๋ก ์ด๊ธฐํ
for(let i=0; i< word1.length; ++i){
for(let j=0; j <= word2.length;++j){
if(i==0 || j==0){
lcsarr[i][j] = 0;
} else {
if(word1[i-1] == word2[j-1]){
lcsarr[i][j] = lcsarr[i-1][j-1]+1;
} else {
lcsarr[i][j] = 0;
}
}
if(max<lcsarr[i][j]){
max = lcsarr[i][j];
index = i;
}
}
}
let str = '';
if(max == 0){
return str;
} else {
for(let i=index-max; i< max;++i){
str+=word2[i];
}
return str;
}
}
print(lcs('abbcc','dbbcc')); // bb
knapsack ๋ฌธ์
์๊ณ ๋ฆฌ์ฆ ์ฐ๊ตฌ์์ ์์ฃผ ๋ฑ์ฅํ๋ knapsack ๋ฌธ์ ๋ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๋ฅผ ๋ค๋ฃฌ๋ค.
์จ๊ฐ ๋ณด๋ฌผ๋ค์ด ๊ฐ๋ ์ฐฌ ๊ธ๊ณ ๋ฅผ ํธ ์ ์๊ฒ ๋์๋ค๊ณ ํ์. ๊ทผ๋ฐ ์ด ๋ง์ ๋ณด๋ฌผ๋ค์ ๋ด์ ์ ์๋ ๊ฑด ์์ ๋ฐฑํฉ๋ฟ์ด๋ค.
๊ฐ ์์ดํ ์ ํฌ๊ธฐ์ ๊ฐ์ด ๋ค๋ฅด๊ณ , ๋ฐฑํฉ์ ์ฑ์์ ๊ฐ๋ฅํ ๊ฐ์ด์น๊ฐ ๋์ ์์ดํ ์ผ๋ก ์ฑ์ฐ๊ณ ์ถ๋ค๊ณ ํ์.
์์ดํ . ๐ ๐ ๐ฎ ๐บ
ํฌ๊ธฐ 3 4 7 8 9
๊ฐ 4 5 10 11 13
๋ฐฑํฉ์ ํฌ๊ธฐ : 16๋ผ๊ณ ํ ๋, ๐ + ๐บ = ํฌ๊ธฐ (7+9), ๊ฐ(10+13)์ ๊ฐ์ ธ๊ฐ๋ ๊ฒ ๊ฐ์ฅ ์ด์ต์ด๋ค.
๋จผ์ ์ฌ๊ท์ ์ผ๋ก ํด๋น ์๊ณ ๋ฆฌ์ฆ์ ์ฝ๋๋ก ์์ฑํด ๋ณด์.
function max(a, b) {
return (a > b) ? a : b;
}
function knapsack(capacity, size, value, n) {
if (n == 0 || capacity == 0) {
return 0;
}
if (size[n-1] > capacity) {
return knapsack(capacity, size, value, n-1);
} else {
return max(value[n-1] + knapsack(capacity-size[n-1], size, value, n-1), knapsack(capacity, size, value, n-1));
}
}
const value = [4,5,10,11,13];
const size = [3,4,7,8,9];
const capacity = 16;
const n = 5;
print(knapsack(capacity, size, value, n)); // 23
์ฌ๊ท์ ์ธ ํด๊ฒฐ๋ฒ์ ๊ฐ์ ์ผ์ด์ค๋ค์ ์ฌ๋ฐฉ๋ฌธํ๊ธฐ ๋๋ฌธ์ ๋นํจ์จ์ ์ด๋ค. DP๋ก ๊ตฌํํด ๋ณด์.
function print(item){
console.log(item);
}
function max(a, b) {
return (a > b) ? a : b;
}
function dKnapsack(capacity, size, value, n) {
let K = [];
for (let i = 0; i <= n; i++) {
K[i] = [];
for (let w = 0; w <= capacity; w++) {
if (i == 0 || w == 0) {
K[i][w] = 0;
} else if (size[i-1] <= w) {
K[i][w] = max(value[i-1] + K[i-1][w-size[i-1]], K[i-1][w]);
} else {
K[i][w] = K[i-1][w];
}
}
}
return K[n][capacity];
}
let values = [4,5,10,11,13];
let sizes = [3,4,7,8,9];
let capacity = 16;
let n = values.length;
print(dKnapsack(capacity, sizes, values, n)); // 23
Greedy Algorithms
๊ฑฐ์ค๋ฆ๋ ์ฃผ๊ธฐ
!! ์ฑ ์ cent๋ก ๋์ด ์์ต๋๋ค. ์ํ๋ก ๋ณ๊ฒฝํ์ฌ ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํํ์ต๋๋ค!!
ํธ์์ ์์ 1230์์ ๊ฑฐ์ฌ๋ฌ ๋ฐ์์ผ ํ๋ค๊ณ ํ ๋, ์ง์์ ์ด๋ป๊ฒ ์ต์ํ์ ๋์ ๊ฐ์๋ก ๊ฑฐ์ฌ๋ฌ์ค ์ ์์๊น?
10์์ง๋ฆฌ, 50์์ง๋ฆฌ, 100์์ง๋ฆฌ, 500์์ง๋ฆฌ ์ค์์ ๊ณจ๋ผ์ ์ค ์ ์๋ค๊ณ ํ ๋ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํํ ์ ์๋ค.
function print(item){
console.log(item);
}
function makeChange(origAmt, coins) {
let remainAmt = 0;
if (origAmt % 500 < origAmt) {
coins[3] = parseInt(origAmt / 500);
remainAmt = origAmt % 500;
origAmt = remainAmt;
}
if (origAmt % 100 < origAmt) {
coins[2] = parseInt(origAmt / 100);
remainAmt = origAmt % 100;
origAmt = remainAmt;
}
if (origAmt % 50 < origAmt) {
coins[1] = parseInt(origAmt / 50);
remainAmt = origAmt % 50;
origAmt = remainAmt;
}
coins[0] = parseInt(origAmt / 10);
}
function showChange(coins) {
if (coins[3] > 0) {
print("Number of 500 Won coins - " + coins[3] + " - " + coins[3] * 500);
}
if (coins[2] > 0) {
print("Number of 100 Won coins - " + coins[2] + " - " + coins[2] * 100);
}
if (coins[1] > 0) {
print("Number of 50 Won coins - " + coins[1] + " - " + coins[1] * 50);
}
if (coins[0] > 0) {
print("Number of 10 Won coins - " + coins[0] + " - " + coins[0] * 10);
}
}
let origAmt = 1230;
let coins = [];
makeChange(origAmt, coins);
showChange(coins);
/**
Number of 500 Won coins - 2 - 1000
Number of 100 Won coins - 2 - 200
Number of 10 Won coins - 3 - 30
*/
knapsack ๋ฌธ์
์ด์ ์๋ DP๋ก knapsack ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ์๊ณ ๋ฆฌ์ฆ๊ณผ ์ฌ๊ท์ ์ผ๋ก ํด๊ฒฐํ๋ ์๊ณ ๋ฆฌ์ฆ์ ์ดํด๋ดค๋ค.
์ด๋ฒ์๋ ๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ๊ตฌํํด ๋ณด์.
๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก knapsack ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์ ํ ๋ ๋ฐฑํฉ ์์ ๋ฃ์ ์์ดํ ๋ค์ด ์ฐ์์ ์ธ ๋ฐ์ดํฐ๋ผ๊ณ ๊ฐ์ ํ๋ค.
์๋ฅผ ๋ค๋ฉด ์ฒ์ด๋ ์ฌ๊ธ์ฒ๋ผ ํ๋ํ๋ ์ ์ ์๋ ๋จ์๋ก ๋๋๋ ๊ฒ ์๋๋ผ ์ ์ฒด ๋ฉด์ ์ด๋ ๋ถํผ๋ฅผ ๊ตฌํ๋ฏ์ด ๋ค๋ฃจ๋ฉด ๋๋ค.
์ต์ ์ ํด๋ ๋ฐฑํฉ ๊ณต๊ฐ์ด ์๊ฑฐ๋ ์์ดํ ์ด ์์ง๋ ๋๊น์ง ๊ฐ์ฅ ๋์ ๊ฐ๋ค์ ๋ฐฑํฉ์ ๋ฃ๋ ๊ฒ์ด๋ค.
๊ทธ๋ค์์๋ ๊ฐ๋ฅํ ๊ฐ์ด ๋์ ์์ดํ ์ ๋ฃ๊ณ , ์ด ๊ณผ์ ์ ๋ฐ๋ณตํ๋ ๊ฒ์ด๋ค.
์ฐ์์ ์ธ ๋ฐ์ดํฐ๋ก ์ต์ ์ ๊ทธ๋ฆฌ๋ ํด๋ฅผ ๊ตฌํ๋ ์ด์ ๋ ๋ฐฑํฉ ์์ ํ
๋ ๋น์ ๋ฐ ๊ฐ๋ฅผ ๋ฃ์ ์ ์๊ณ , ์์ ์์ดํ
์ ๋ฃ๊ฑฐ๋ ๋ฃ์ ์ ์๋ ๊ฒฝ์ฐ๋ก๋ง ๋๋๋ค.
์๊ณ ๋ฆฌ์ฆ์ ๋ก์ง์ ๋ค์๊ณผ ๊ฐ๋ค.
1. ๋ฐฑํฉ ์ฉ์ ์ด W์ด๊ณ , ์์ดํ
์ด ๊ฐ๊ฐ ๊ฐ์ด์น๊ฐ V์ด๊ณ ๋ฌด๊ฒ๊ฐ w์ผ ๊ฒฝ์ฐ, v/w ๋น์จ(๋ฌด๊ฒ ๋๋น ๊ฐ์น, ๊ฐ์ฑ๋น)๋ก ์์ดํ
๋ค์ ๋ด๋ฆผ์ฐจ์ ์์๋๋ก ์ ๋ ฌํ์.
2. ๊ฐ ์์ดํ ์ ๋ค์ ์ด ๋น์จ๋ก ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌํ์.
3. ๊ฐ์ฅ ๋น์จ์ด ๋์ ์์ดํ ๋ถํฐ ๋ฐฑํฉ์ ๋ฃ๊ณ , ์์ ํ ๋ฃ์ ์ ์๋ ๊ฒฝ์ฐ์๋ ๊ฐ๋ฐฉ์ด ๊ฐ๋ ์ฐฌ ๊ฒ์ด๋ค.
์ฝ๋๋ก ์ฎ๊ธฐ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
function ksack(values, weights, capacity) {
let load = 0;
let i = 0;
let w = 0;
while (load < capacity && i < 4) {
if (weights[i] <= (capacity-load)) {
w += values[i];
load += weights[i];
} else {
let r = (capacity-load)/weights[i]; w += r * values[i];
load += weights[i];
}
++i;
}
return w;
}
let items = ["A", "B", "C", "D"];
let values = [50, 140, 60, 60];
let weights = [5, 20, 10, 12];
let capacity = 30;
print(ksack(values, weights, capacity)); // 220
๐ ๋ง์น๋ฉด์
์ค๋์ ์ฌํ ์๊ณ ๋ฆฌ์ฆ์ธ dp์ ๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ์ ๋ํด ์ดํด๋ดค๋ค.
์๋ !๐ฅณ
๐ Reference
- Data Structures and Algorithms Using Javaโ Script by Michael McMillian (O’Reilly). Copyright 2014 Michael McMillan, 978-1-449-36493-9