당신은 어떤 그래픽 처리 라이브러리를 제작하고 있다. 라이브러리의 사용자는 다양한 단위를 이용해 데이터를 입출력하기 때문에 이 라이브러리에는 단위 변환기가 포함되어야 한다. 아래 조건에 따라 단위 변환 함수를 제작하라.
단위 변환기는 다음 단위들을 입력받아 다른 단위로 변환할 수 있어야 한다.
inch(인치)
cm(센티미터)
mm(밀리미터)
px(픽셀)
pt(포인트)
dxa(20분 포인트)
emu(EMU)
당신은 변환율 상수를 꼭 필요한 만큼만 정의할 생각이다. 라이브러리의 메모리 사용량을 최소화하는 목적도 있고, 여러 개의 상수를 손으로 입력하다 보면 실수로 버그를 만들 위험도 있기 때문이다. 당신은 백과사전을 뒤져서 믿을 수 있는 변환율 여섯 개를 찾아냈다. 당신은 아래에 있는 변환율만을 정의하여야 하며, 각 단위에서 다른 단위로 모든 경우의 변환을 지원해야 한다.
1 inch = 2.54 cm
1 cm = 10 mm
1 inch = 72 pt
1 inch = 96 px
1 pt = 20 dxa
1 dxa = 635 emu
입력: 단위 변환기는 두 개의 인수를 입력받는다. 첫 번째 인수는 한 단위의 수를 표현한 문자열이고 두 번째 인수는 변환하고자 하는 단위를 표현한 문자열이다.
출력: 변환된 수와 단위를 문자열로 출력한다.
입출력예:
param1 param2 result
===================================
"10 cm" "cm" "10 cm"
"10 inch" "mm" "254 mm"
"1024 px" "pt" "768 pt"
"768 px" "inch" "8 inch"
"9144000 emu" "inch" "10 inch"
"12000 dxa" "px" "800 px"
51개의 풀이가 있습니다.
받은 값을 inch로 풀었다가 재변환 하는 방식으로 하였습니다. 그런데 보면 볼수록 제가 문제 의도에 맞게 한건지 의문이 드네요 -.-
/**
1 inch = 2.54 cm
1 cm = 10 mm
1 inch = 72 pt
1 inch = 96 px
1 pt = 20 dxa
1 dxa = 635 emu
param1 param2 result
===================================
"10 cm" "cm" "10 cm"
"10 inch" "mm" "254 mm"
"1024 px" "pt" "768 pt"
"768 px" "inch" "8 inch"
"9144000 emu" "inch" "10 inch"
"12000 dxa" "px" "800 px"
*/
import java.util.HashMap;
import java.util.Scanner;
public class UnitConverter {
private static String[] unitList = { "inch", "cm", "mm", "pt", "px", "dxa", "emu" };
private static double[] procList = { 1, 2.54, 2.54*10 , 72, 96, 20*72, 635*20*72};
private static HashMap<String, Double> unitMap = new HashMap<String, Double>();
public static void main(String[] args) {
int uSize = unitList.length;
for(int i=0;i<uSize;i++){
unitMap.put(unitList[i], procList[i]);
}
Scanner input = new Scanner(System.in);
System.out.print("param1 : "); String in1 = input.nextLine();
System.out.print("param2 : "); String in2 = input.nextLine();
System.out.print("param3 : "); String in3 = input.nextLine();
System.out.println(convert(in1, in2, in3));
}
private static String convert(String in1, String in2, String in3) {
double input = Double.valueOf(in1);
double unitValue, convertValue;
if(unitMap.containsKey(in2) && unitMap.containsKey(in3)){
unitValue = unitMap.get(in2);
convertValue = unitMap.get(in3);
}else{
return "No unit in the registered list.";
}
return (int)(input / unitValue * convertValue) + " " + in3;
}
}
아, 어려웠습니다. ㅜㅜ
단위 변환시 방향이 섞여있어서 한참 헤멨습니다.
풀긴 했는데 왠지 개운하지 않은 이 느낌은...
파이썬입니다.
import unittest
class U:
def __init__(self, name):
self.name = name
self.parent = None
self.rate_list = []
self.value = 1.0
def set_rate(self, u, value):
u.set_parent(self)
u.value = value
self.rate_list.append(u)
def set_parent(self, u):
self.parent = u
def get_parent(self):
return self.parent
def get_path(self, to):
a = self._get_path(to, [to])
b = to._get_path(self, [self])
if len(a) >= len(b):
return reversed(a)
else:
return b
def _get_path(self, to, path=[]):
if self == to: return path
parent = to.get_parent()
if not parent:
path.append(self)
else:
path.append(parent)
self._get_path(parent, path)
return path
def get_rate(self, to):
rate = 1.0
path = list(self.get_path(to))
for i in range(len(path)):
if i+1 < len(path): next = path[i+1]
else: next = None
if next in path[i].rate_list:
rate = rate * next.value
elif next:
rate = rate / path[i].value
return rate
def change(self, to, value):
rate = self.get_rate(to)
return value * rate
def __str__(self):
return self.name
def exchange(fr, to):
inch = U("inch")
cm = U("cm")
pt = U("pt")
px = U("px")
dxa = U("dxa")
emu = U("emu")
mm = U("mm")
inch.set_rate(cm, 2.54)
inch.set_rate(pt, 72.0)
inch.set_rate(px, 96.0)
cm.set_rate(mm, 10.0)
pt.set_rate(dxa, 20.0)
dxa.set_rate(emu, 635.0)
fr_v, fr = fr.split()
fr = eval(fr)
to = eval(to)
r = int(fr.change(to, int(fr_v)))
return "%s %s" % (r, to.name)
class UnitTest(unittest.TestCase):
def test1(self):
self.assertEquals("10 cm", exchange("10 cm", "cm"))
self.assertEquals("254 mm", exchange("10 inch", "mm"))
self.assertEquals("768 pt", exchange("1024 px", "pt"))
self.assertEquals("8 inch", exchange("768 px", "inch"))
self.assertEquals("10 inch", exchange("9144000 emu", "inch"))
self.assertEquals("800 px", exchange("12000 dxa", "px"))
if __name__ == "__main__":
unittest.main()
unit = {'inch':1,
'cm':2.54,
'mm':25.4,
'pt':72,
'px':96,
'dxg':72*20,
'emu':72*20*635
}
def chg_unit(param1, param2):
num, du = param1.split(" ")
cu = param2
print (num, du, float(num)*unit[cu]/unit[du], cu)
chg_unit("10 cm", "cm")
chg_unit("10 inch", "mm")
chg_unit("1024 px", "pt")
chg_unit("768 px", "inch")
chg_unit("9144000 emu", "inch")
chg_unit("12000 dxg", "px")
문제의 뜻에서 주어진 단위 변환 법칙 외에는 쓰지 말라는 것에 충실하게 풀었습니다.
단위 변환을 큐로 사용하고, 변환된 결과값은 리스트에 저장합니다.
큐에서 하나를 꺼내서 결과리스트에 적용해보되, 적용되는 값이 있으면, 변환해서 리스트에 추가하고
큐에서 꺼낸 단위변환법칙은 버립니다. 적용되는 값이 없으면 큐에 다시 넣습니다.
원하는 단위가 나올때까지 반복합니다.
def conv(i,o,n): #i : input measure, o: output mearsue, n : number
measure=[ ('inch','cm',2.54),
('cm','mm',10),
('inch','pt',72),
('inch','px',96),
('pt','dxa',20),
('dxa','emu',635) ]
n=float(n)
if i==o: return n
res=[(i,n)]
while measure:
mi,mo,m=measure.pop(0)
used = False
for j in range(len(res)):
i,n = res[j]
if i==mi :
res.append((mo, n*m))
if mo == o : return n*m
used=True
if i==mo :
res.append((mi, n/m))
if mi == o :return n/m
used=True
if not used :measure.append((mi,mo,m))
print conv('cm','cm',10)
print conv('inch','mm',10)
print conv('px','pt',1024)
print conv('px','inch',768)
print conv('emu','inch',9144000)
print conv('dxa','px',12000)
def convert (num,current,target):
arr = [['inch','cm',2.54],['cm','mm',10],['inch','pt',72],\
['inch','px',96],['pt','dxa',20],['dxa','emu',635]]
while True:
if current==target:
break
else:
for k in arr:
if current in k:
if k.index(current)==0:
num *= k[2]
current =k[1]
elif k.index(current)==1:
num *= 1/k[2]
current =k[0]
if current in k and target in k:
break
if current in k and target in k:
break
return num
param1 = input("param1을 입력하시오").split(" ")
param2 = input("param2을 입력하시오")
result = convert(int(param1[0]),param1[1],param2)
print(result,' ',param2)
6개의 변환율을 2차원 배열화 하고, 변환 하려는 단위와, target 단위를 변수에 담고 변환율을 담은 배열을 순환하면서 계산하는 방식을 이용했습니다
// SP_UnitConvert.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
#include "stdafx.h"
#include <string>
typedef struct st_MAP_
{
char ch[4];
st_MAP_* pBefore;
double fScale;
st_MAP_()
{
memset(this,0,sizeof(st_MAP_));
fScale = 1;
};
}MAP,*PMAP;
double GetScale(char* p,PMAP pMap,int nSize)
{
float fScale = 1;
for(int iter = 0 ; iter < nSize ; iter ++,pMap++)
{
if(strcmp(pMap->ch,p) == 0)
{
while(pMap)
{
fScale*= pMap->fScale;
pMap = pMap->pBefore;
}
break;
}
}
return fScale;
}
int _tmain(int argc, _TCHAR* argv[])
{
MAP map[6];
strcpy(map[0].ch ,"cm"); map[0].fScale = 2.54 ; map[0].pBefore = NULL;
strcpy(map[1].ch ,"mm"); map[1].fScale = 10; map[1].pBefore = &map[0];
strcpy(map[2].ch ,"pt"); map[2].fScale = 72; map[2].pBefore = NULL;
strcpy(map[3].ch ,"px"); map[3].fScale = 96; map[3].pBefore = NULL;
strcpy(map[4].ch ,"dxa"); map[4].fScale = 20; map[4].pBefore = &map[2];
strcpy(map[5].ch ,"emu"); map[5].fScale = 635; map[5].pBefore = &map[4];
while(1)
{
int nInput = 0;
char chInputUnit[5];
char chResultUnit[5];
printf("?");
scanf("%d %s %s",&nInput,chInputUnit,chResultUnit);
double fScaleResult = GetScale(chResultUnit,map,6);
double fScaleInput = GetScale(chInputUnit,map,6);
printf("%d %s\n",(int)(nInput * fScaleResult / fScaleInput),chResultUnit);
}
return 0;
}
def convert(from, to)
units = {inch: 1, cm: 2.54, mm: 2.54*10, pt: 72, px: 96, dxa: 20*72, emu: 635*20*72}
from.split(" ")
.each_cons(2).to_a
.map{|s, u| (s.to_f / units[u.to_sym] * (units[to.to_sym] * 100) / 100)}
.map{|i| i == i.to_i ? i.to_i : i}
.first.to_s + " " + to
end
require 'test/unit'
extend Test::Unit::Assertions
assert_equal convert("10 cm", "cm"), "10 cm"
assert_equal convert("10 inch", "mm"), "254 mm"
assert_equal convert("1024 px", "pt"), "768 pt"
assert_equal convert("768 px", "inch"), "8 inch"
assert_equal convert("9144000 emu", "inch"), "10 inch"
assert_equal convert("12000 dxa", "px"), "800 px"
const inch = 1;
const cm = 2.54;
const mm = 25.4;
const px = 96;
const pt = 72;
const dxa = 1440;
const emu = 914400;
var inParam = 0;
var doc = document;
function goCalc(){
var inselect = document.getElementById('inselect');
var outselect = document.getElementById('outselect');
var inIndex = inselect.selectedIndex;
var outIndex = outselect.selectedIndex;
var inVal = inselect[inIndex].value;
var outVal = outselect[outIndex].value;
inParam = doc.getElementById('inBox').value;
doc.getElementById('outBox').value = "";
console.log(inVal + " => " +outVal);
if(inIndex != outIndex){
//변환 할려는 단위가 다를 경우만 계산한다.
//입력한 값을 inch로 바꾼다.
var tmpCalc = 0;
var result = 0;
switch(inIndex){
case 0:
tmpCalc = inParam;
break;
case 1:
tmpCalc = inParam / cm;
break;
case 2:
tmpCalc = inParam / mm;
break;
case 3:
tmpCalc = inParam / px;
break;
case 4:
tmpCalc = inParam / pt;
break;
case 5:
tmpCalc = inParam / dxa;
break;
case 6:
tmpCalc = inParam / emu;
break;
}
console.info("tmp =>"+tmpCalc);
switch(outIndex){
case 0:
result = tmpCalc;
break;
case 1:
result = tmpCalc * cm;
break;
case 2:
result = tmpCalc * mm;
break;
case 3:
result = tmpCalc * px;
break;
case 4:
result = tmpCalc * pt;
break;
case 5:
result = tmpCalc * dxa;
break;
case 6:
result = tmpCalc * emu;
break;
}
doc.getElementById('outBox').value = result;
}else{ //수치가 같은 경우
doc.getElementById('outBox').value = doc.getElementById('inBox').value;
}
}
기준을 인치로 했습니다.
아래는 html까지 포함 입니다.
<html>
<head>
<script>
// 당신은 어떤 그래픽 처리 라이브러리를 제작하고 있다. 라이브러리의 사용자는 다양한 단위를 이용해 데이터를 입출력하기 때문에 이 라이브러리에는 단위 변환기가 포함되어야 한다. 아래 조건에 따라 단위 변환 함수를 제작하라.
// 단위 변환기는 다음 단위들을 입력받아 다른 단위로 변환할 수 있어야 한다.
// inch(인치)
// cm(센티미터)
// mm(밀리미터)
// px(픽셀)
// pt(포인트)
// dxa(20분 포인트)
// emu(EMU)
// 입력받은 수를 인치로 변환한다.
// 원하는 결과를 인치에서 변환한다.
// 인치를 기준으로 변수를 선언한다.
const inch = 1;
const cm = 2.54;
const mm = 25.4;
const px = 96;
const pt = 72;
const dxa = 1440;
const emu = 914400;
var inParam = 0;
var doc = document;
function goCalc(){
var inselect = document.getElementById('inselect');
var outselect = document.getElementById('outselect');
var inIndex = inselect.selectedIndex;
var outIndex = outselect.selectedIndex;
var inVal = inselect[inIndex].value;
var outVal = outselect[outIndex].value;
inParam = doc.getElementById('inBox').value;
doc.getElementById('outBox').value = "";
console.log(inVal + " => " +outVal);
if(inIndex != outIndex){
//변환 할려는 단위가 다를 경우만 계산한다.
//입력한 값을 inch로 바꾼다.
var tmpCalc = 0;
var result = 0;
switch(inIndex){
case 0:
tmpCalc = inParam;
break;
case 1:
tmpCalc = inParam / cm;
break;
case 2:
tmpCalc = inParam / mm;
break;
case 3:
tmpCalc = inParam / px;
break;
case 4:
tmpCalc = inParam / pt;
break;
case 5:
tmpCalc = inParam / dxa;
break;
case 6:
tmpCalc = inParam / emu;
break;
}
console.info("tmp =>"+tmpCalc);
switch(outIndex){
case 0:
result = tmpCalc;
break;
case 1:
result = tmpCalc * cm;
break;
case 2:
result = tmpCalc * mm;
break;
case 3:
result = tmpCalc * px;
break;
case 4:
result = tmpCalc * pt;
break;
case 5:
result = tmpCalc * dxa;
break;
case 6:
result = tmpCalc * emu;
break;
}
doc.getElementById('outBox').value = result;
}else{ //수치가 같은 경우
doc.getElementById('outBox').value = doc.getElementById('inBox').value;
}
}
</script>
</head>
<body>
<input type="inputbox" id="inBox"/>
<select id="inselect" onchange="goCalc();">
<option value="inch">inch</option>
<option value="cm">cm</option>
<option value="mm">mm</option>
<option value="px">px</option>
<option value="pt">pt</option>
<option value="dxa">dxa</option>
<option value="emu">emu</option>
</select>
<strong>-></strong>
<select id="outselect" onchange="goCalc()";>
<option value="inch">inch</option>
<option value="cm">cm</option>
<option value="mm">mm</option>
<option value="px">px</option>
<option value="pt">pt</option>
<option value="dxa">dxa</option>
<option value="emu">emu</option>
</select>
<input type="inputbox" id="outBox" readonly="true"/>
<input type="button" id="goBtn" value="go" />
<script>
document.getElementById("inBox").focus();
</script>
</body>
</html>
clojure
(ns t1.core
(:require [loom.graph :as graph]
[loom.alg :as alg]))
;; ref: https://github.com/aysylu/loom
(def dic-rate-of-transformation*
{:inch {:cm 2.54
:pt 72
:px 96}
:cm {:mm 10}
:pt {:dxa 20}
:dxa {:emu 635}})
(def wg* (graph/weighted-graph dic-rate-of-transformation*))
(defn- dir-w [[from to]]
(let [ff (from dic-rate-of-transformation*)]
(if (and ff (to ff))
(to ff)
(/ 1 (from (to dic-rate-of-transformation*))))))
(defn- calc-delta [from to]
(when-let [path (alg/dijkstra-path wg* from to)]
(->> path
(partition 2 1)
(map dir-w)
(reduce *))))
(let [standard-unit :inch
units [:inch :cm :mm :pt :px :dxa :emu]]
(into {}
(for [unit units]
[unit (calc-delta standard-unit unit)])))
;=> {:inch 1, :cm 2.54, :mm 25.4, :pt 72, :px 96, :dxa 1440, :emu 914400}
(for [[n from to] [[10 :cm :cm]
[10 :inch :mm]
[1024 :px :pt]
[768 :px :inch]
[9144000 :emu :inch]
[12000 :dxa :px]]]
(when-let [delta (calc-delta from to)]
[(* n delta) to]))
;=> ([10 :cm] [254.0 :mm] [768N :pt] [8N :inch] [10N :inch] [800N :px])
Perl
sub conv{
my %u=(
inch=> 2.54*10, cm => 10, mm => 1,
pt => 2.54*10/72, px=> 2.54*10/96,
dxa => 2.54*10/72/20,
emu => 2.54*10/72/20/635
);
my($from,$to)=@_;
$from=~s|(\d+) (\w+)|$1*$u{$2}/$u{$to}." $to"|e;
$from;
}
루비입니다. 평범하게 풀었습니다.
class Unit
CONVERTS = {
"inch" => 1,
"cm" => 2.54,
"mm" => 2.54 * 10,
"pt" => 72,
"px" => 96,
"dxa" => 20 * 72,
"emu" => 635 * 20 * 72
}
attr_reader :number, :unit
def initialize(str)
number, @unit = str.split(" ")
@number = number.to_i
end
def convert_to(u)
"#{number * CONVERTS[u] / CONVERTS[unit]} #{u}"
end
end
def exchange(string, unit)
Unit.new(string).convert_to(unit)
end
p exchange("10 cm", "cm") # "10 cm"
p exchange("10 inch", "mm") # "254 mm"
p exchange("1024 px", "pt") # "768 pt"
p exchange("768 px", "inch") # "8 inch"
p exchange("9144000 emu", "inch") # "10 inch"
p exchange("12000 dxa", "px") # "800 px"
Sub main()
Dim dcs() As Double = {1 / 2.54,
1,
10,
96 / 2.54,
72 / 1 / 2.54,
20 * 72 / 1 / 2.54,
635 * 20 * 72 / 1 / 2.54}
Dim units() As String = {"inch", "cm", "mm", "px", "pt", "dxa", "emu"}
Dim param1 As String = Console.ReadLine
Dim cvUnit As String = Console.ReadLine.ToLower
Dim num As Double = Val(Split(param1, " ")(0))
Dim unit As String = Trim(Split(param1, " ")(1)).ToLower
num = dcs(Array.IndexOf(units, unit)) ^ -1 * num * dcs(Array.IndexOf(units, cvUnit))
Console.WriteLine("Result: {0} {1}", num, cvUnit)
Console.ReadLine()
End Sub
대부분 inch를 기준으로 두셧길래 cm를 기준으로 두고 만들어봤습니다.
C++ 로 컨버팅해보았습니다.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
int indexOf(char* arr[], char *itm);
int main() {
float v;
char *unit = (char*) malloc(20);
char *cvUnit = (char*) malloc(20);
char* units[] = { "inch", "cm", "mm", "px", "pt", "dxa", "emu" };
float dcs[] = { 1 / 2.54, 1, 10, 96 / 2.54, 72 / 1 / 2.54, 20 * 72 / 1 / 2.54, 635 * 20 * 72 / 1 / 2.54 };
scanf("%f %s %s", &v, unit, cvUnit);
v = pow(dcs[indexOf(units, unit)], -1) * v * dcs[indexOf(units, cvUnit)];
printf("%f %s", v, cvUnit);
return 0;
}
int indexOf(char* arr[], char *itm) {
for (int i = 0; i < 7; i++){
if (!strcmp(arr[i], itm)) {
return i;
}
}
return -1;
}
static void exce21()
{
Scanner scan = new Scanner(System.in);
String[] str = scan.nextLine().split(" ");
String[] units = { "inch", "cm", "mm", "pt", "px", "dxa", "emu" };
int u_idx = 0;
String out = scan.nextLine();
double n = Double.parseDouble(str[0]);
for (int i = 0; i < units.length; i++)
{
if (str[0].equals(units[i]))
{
u_idx = i;
break;
}
}
// {"inch","cm","mm","pt","px","dxa","emu"};
switch (u_idx)
{
case 0:
break;
case 1:
n /= 2.54;
break;
case 2:
n /= 25.4;
break;
case 3:
n /= 72;
break;
case 4:
n /= 96;
break;
case 5:
n /= (20 * 72);
break;
case 6:
n /= (635 * 20 * 72);
break;
}
for (int i = 0; i < units.length; i++)
{
if (out.equals(units[i]))
{
u_idx = i;
break;
}
}
switch (u_idx)
{
case 0:
break;
case 1:
n *= 2.54;
break;
case 2:
n *= 25.4;
break;
case 3:
n *= 72;
break;
case 4:
n *= 96;
break;
case 5:
n *= (20 * 72);
break;
case 6:
n *= (635 * 20 * 72);
break;
}
System.out.printf("%f %s",n,out);
}
mm = 1;inch = 25.4;cm = 10;pt = inch/72;px = inch/96;dxa = pt/20;emu = dxa/635
while __name__ == '__main__':
a = input("param1: "); b = input("param2: ")
tmp = eval(str(eval(a.split()[0]+'*'+a.split()[1]))+'/'+b)
print(str(tmp)+' '+b)
생각을 바꾸면 쉽습니다. 파이썬 3.5.1
Ruby
unit = %w(inch cm mm pt px dxa emu).zip([1,2.54,25.4,72,96,20*72,635*20*72]).to_h
conv = ->from,to { n,u=from.split; ["%g" % (unit[to]/unit[u])*n.to_i, to]*' ' }
Test
expect( conv["10 cm", "cm"] ).to eq "10 cm"
expect( conv["10 inch", "mm"] ).to eq "254 mm"
expect( conv["1024 px", "pt"] ).to eq "768 pt"
expect( conv["768 px", "inch"] ).to eq "8 inch"
expect( conv["9144000 emu", "inch"] ).to eq "10 inch"
expect( conv["12000 dxa", "px"] ).to eq "800 px"
뭔가 주어진 변환표를 그대로 써야 하는 문제인지 애매한데, 가장 간단한 방법은 대표로 삼을 단위 하나를 두고 해당 단위로 변환한 다음 목적 단위로 재변경하는 겁니다. 따라서 변환표는 대표 단위와 각 단위의 짝들로 이루어지면 되죠.
def convert(x, y):
table_from_inch = {
'inch': 1,
'cm': 2.54,
'mm': 25.4,
'px': 96,
'pt': 72,
'dxa': 20*72,
'emu': 72*20*635
}
a, b = x.split()[:2]
a = float(a)
return round(i / table_from_inch[x] * table_from_inch[y])
a=input().split(" ")
data1=int(a[0])
data2=a[1]
data3=a[2]
inch={"inch":1,"cm":2.54,"mm":25.4,"pt":72,"px":96,"dxa":1440,"emu":914400}
inchdata=data1/inch.get(data2)
result=inchdata*inch.get(data3)
print(str(data1)+" "+data2+" | "+data3+" | "+str(result)+" "+data3)
taba = ('inch', 'cm', 'mm')
mula = (1, 2.54, 10)
tabb = ('inch', 'pt', 'dxa', 'emu')
mulb = (1, 72, 20, 635)
tabc = ('inch', 'px')
mulc = (1, 96)
def toinch(a, b):
result = 1
if b in taba:
for muls in mula[:taba.index(b)+1]: result = result * muls**(-1)
elif b in tabb :
for muls in mulb[:tabb.index(b)+1]: result = result * muls**(-1)
elif b in tabc :
for muls in mulc[:tabc.index(b)+1]: result = result * muls**(-1)
return result * a
def frominch(a, b):
result = 1
if b in taba:
for muls in mula[:taba.index(b)+1]: result = result * muls
elif b in tabb :
for muls in mulb[:tabb.index(b)+1]: result = result * muls
elif b in tabc :
for muls in mulc[:tabc.index(b)+1]: result = result * muls
return result * a
def trans(a, b, c):
print('Trans', str(a)+b, "to '", c, "' is", str(frominch(toinch(a, b), c))+c )
return frominch(toinch(a, b), c)
trans(10, 'cm', 'cm')
trans(10, 'inch', 'mm')
trans(1024, 'px', 'pt')
trans(9144000, 'emu', 'inch')
trans(12000, 'dxa', 'px')
아예 단위의 명칭과 환산단위를 각각 튜플로 만들어서 해당 값을 동일한 index로 찾아내도록 해 보았습니다. dict object 등을 사용하려고 해도 오히려 역방향으로 계산하려니 복잡해지더라구요..
C#으로 작성했습니다.
using System.Collections;
using System.Collections.Generic;
public string PrintConvertedUnit(Hashtable unitMap, double rate, string unitA, string unitB)
{
var convertValue = 0d;
var unitValue = 0d;
if (unitMap.ContainsKey(unitA) && unitMap.ContainsKey(unitB))
{
convertValue = (double) unitMap[unitB];
unitValue = (double) unitMap[unitA];
}
return (int) (rate/unitValue*convertValue) + " " + unitB;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
double convert(double value, char* param1, char* param2);
double InchtoVal(double inch, char* param);
void main(void) {
char s1[] = "12000 dxa px";
char s2[] = " ";
char* token = NULL;
char* param1;
char* param2;
double value;
token = strtok(s1, s2);
value = atoi(token);
param1= strtok(NULL, s2);
param2= strtok(NULL, s2);
printf("param1 \tparam2\t\treslut\n");
printf("=======================================\n");
printf("\"%0.f%s\"\t\"%s\"\t", value, param1, param2);
printf("\t\"%0.f %s\"\n", convert(value, param1, param2), param2);
}
double InchtoVal(double inch, char* param) {
double cm, mm, px, pt, dxa, emu;
cm = inch * 2.54;
mm = cm * 10;
px = 96 * inch;
pt = 72 * inch;
dxa = pt * 20;
emu = dxa * 635;
if(!strcmp(param, "inch"))
return inch;
if(!strcmp(param, "cm"))
return cm;
if(!strcmp(param, "mm"))
return mm;
if(!strcmp(param, "px"))
return px;
if(!strcmp(param, "pt"))
return pt;
if(!strcmp(param, "dxa"))
return dxa;
if(!strcmp(param, "emu"))
return emu;
return 0;
}
double convert(double value, char* param1, char* param2) {
double inch;
if(!strcmp(param1, "cm")) {
inch = value / 2.54;
return InchtoVal(inch, param2);
}
if(!strcmp(param1, "mm")) {
inch = value / 2.54 / 10;
return InchtoVal(inch, param2);
}
if(!strcmp(param1, "px")) {
inch = value / 96;
return InchtoVal(inch, param2);
}
if(!strcmp(param1, "pt")) {
inch = value / 72;
return InchtoVal(inch, param2);
}
if(!strcmp(param1, "dxa")) {
inch = value / 72 / 20;
return InchtoVal(inch, param2);
}
if(!strcmp(param1, "emu")) {
inch = value / 72 / 20 / 635;
return InchtoVal(inch, param2);
}
if(!strcmp(param1, "inch")) {
inch = value;
return InchtoVal(inch, param2);
}
return 0;
}
import re
map = {
('inch', 'cm'):2.54,
('cm','mm'):10,
('inch','pt'):72,
('inch','px'):96,
('pt','dxa'):20,
('dxa', 'emu'):635
}
def do(src, unit):
m = re.match(r'([^a-zA-Z]*)([a-zA-Z]+)', src)
val = float(m.group(1).strip())
src_unit = m.group(2)
print(src, '->', unit, end=" : ")
def _convert(su, tu, v, history = set()):
r, u = None, None
if su == tu:
r, u = v, tu
elif map.get((su, tu)) != None:
r, u = v * map.get((su, tu)), tu
elif map.get((tu, su)) != None:
r, u = v / map.get((tu, su)), tu
else:
for s_, t_ in map:
if s_ == su and not((su, t_) in history):
history.add((su, t_))
r, u = _convert(su, t_, v, history)
r, u = _convert(u, tu, r, history)
elif t_ == su and not((su, s_) in history):
history.add((su, s_))
r, u = _convert(su, s_, v, history)
r, u = _convert(u, tu, r, history)
if r != None:
break;
return (r, u)
r, u = _convert(src_unit, unit, val)
print(r, u)
do('10 cm', 'cm')
do('10 inch', 'mm')
do('1024 px', 'pt')
do('768 px', 'inch')
do('9144000 emu', 'inch')
do('12000 dxa', 'px')
Python 3.5.2에서 작성하였습니다.
Python 3로 작성하였습니다.
초반에 입력된 데이터를 기반으로 원하는 변환단위가 나올때까지 재귀함수로 검색하는 방식으로 풀이하였습니다.
class Unit:
def __init__(self, value):
self.value = value
def __repr__(self):
return "%f %s" % (self.value, self.__class__.__name__)
class Cm(Unit):pass
class Mm(Unit):pass
class Inch(Unit):pass
class Pt(Unit):pass
class Px(Unit):pass
class Dxa(Unit):pass
class Emu(Unit):pass
class Conversioner:
def __init__(self):
self.conversionMap = {}
def setConversionRatio(self, srcUnit, srcRatio, dstUnit, dstRatio):
if srcUnit not in self.conversionMap:
self.conversionMap[srcUnit] = {}
if dstUnit not in self.conversionMap:
self.conversionMap[dstUnit] = {}
self.conversionMap[srcUnit][dstUnit] = dstRatio/srcRatio
self.conversionMap[dstUnit][srcUnit] = srcRatio/dstRatio
def conversion(self, srcUnitInst, dstUnit):
dstUnitInst = self.doConversion(srcUnitInst, dstUnit)
if dstUnitInst is None:
if type(srcUnitInst) == dstUnit:
dstUnitInst = srcUnitInst
else:
print("%s cannot conversion to %s" % (srcUnitInst.__class__.__name__, dstUnit.__name__))
return
print(">> %s => %s" % (srcUnitInst, dstUnitInst))
def doConversion(self, srcUnitInst, dstUnit, searchList=None):
if searchList == None:
searchList = []
srcUnit = type(srcUnitInst)
if srcUnit == dstUnit:
return None
searchList.append(srcUnit)
if srcUnit in self.conversionMap:
for curUnit in self.conversionMap[srcUnit]:
if curUnit not in searchList:
searchList.append(curUnit)
if curUnit == dstUnit:
dstUnitInst = dstUnit(srcUnitInst.value * self.conversionMap[srcUnit][dstUnit])
return dstUnitInst
curUnitInst = curUnit(srcUnitInst.value * self.conversionMap[srcUnit][curUnit])
findUnitInst = self.doConversion(curUnitInst, dstUnit, searchList)
if findUnitInst:
return findUnitInst
return None
# 단위변환 데이터 입력
conversioner = Conversioner()
conversioner.setConversionRatio(Inch, 1.0, Cm, 2.54)
conversioner.setConversionRatio(Cm, 1.0, Mm, 10.0)
conversioner.setConversionRatio(Inch, 1.0, Pt, 72.0)
conversioner.setConversionRatio(Inch, 1.0, Px, 96.0)
conversioner.setConversionRatio(Pt, 1.0, Dxa, 20.0)
conversioner.setConversionRatio(Dxa, 1.0, Emu, 635.0)
# 단위변환 테스트
conversioner.conversion(Cm(10), Cm)
conversioner.conversion(Inch(10), Mm)
conversioner.conversion(Px(1024), Pt)
conversioner.conversion(Px(768), Inch)
conversioner.conversion(Emu(9144000), Inch)
conversioner.conversion(Dxa(12000), Px)
>> 10.000000 Cm => 10.000000 Cm
>> 10.000000 Inch => 254.000000 Mm
>> 1024.000000 Px => 768.000000 Pt
>> 768.000000 Px => 8.000000 Inch
>> 9144000.000000 Emu => 10.000000 Inch
>> 12000.000000 Dxa => 800.000000 px
import re
#단위를 전부 mm로 바꿈
mm=1
cm=10*mm
inch=2.54*cm
pt=inch/72
px=inch/96
dxa=pt/20
emu=dxa/635
def change_number(param1,param2):
p=re.compile('[a-z]')
q=re.compile('[0-9]')
num=q.findall(param1)
num="".join(num)
before_parameter=p.findall(param1)
before_parameter="".join(before_parameter)
num=int(num)
print("num : ",num,"before parameter : ",before_parameter)
#전부 mm로 변환
if before_parameter=="cm":
before_num=num*cm
elif before_parameter=="inch":
before_num=num*inch
elif before_parameter=="pt":
before_num=num*pt
elif before_parameter=="px":
before_num=num*px
elif before_parameter=="dxa":
before_num=num*dxa
elif before_parameter=="emu":
before_num=num*emu
if param2=="mm":
after_num=before_num
elif param2=="cm":
after_num=before_num/cm
elif param2=="inch":
after_num=before_num/inch
elif before_parameter=="pt":
after_num=num/pt
elif before_parameter=="px":
after_num=num/px
elif before_parameter=="dxa":
after_num=num/dxa
elif before_parameter=="emu":
after_num=num/emu
print(str(int(after_num))+param2)
while True:
param1,param2=input().split()
if param2=="0":
break
else:
change_number(param1,param2)
javascript
var unit = {
"inch" : 1,
"cm" : 2.54,
"pt" : 72,
"mm" : 10 * 2.54,
"pt" : 72,
"px" : 96,
"dxa" : 72 * 20,
"emu" : 72 * 20 * 635
}
var changeunit = function (m, u) {
var [n, c] = m.split(" ");
return `${n / unit[c] * unit[u]} ${u}`;
};
console.log(changeunit("10 cm", "cm"));
console.log(changeunit("10 inch", "mm"));
console.log(changeunit("1024 px", "pt"));
console.log(changeunit("768 px", "inch"));
console.log(changeunit("9144000 emu", "inch"));
console.log(changeunit("12000 dxa", "px"));
# base rates
units = ['inch', 'cm', 'mm', 'px', 'pt', 'dxa', 'emu']
base_rates = {('inch', 'cm') : 2.54,
('cm', 'mm') : 10,
('inch', 'pt') : 72,
('inch', 'px') : 96,
('pt', 'dxa') : 20,
('dxa', 'emu') : 653 }
# init
rates = dict()
for F, T in base_rates:
rates[(F, T)] = base_rates[(F, T)]
rates[(T, F)] = 1 / base_rates[(F, T)]
for U in units:
rates[(U, U)] = 1
# transitive conversion
# F: From, T: To, V: Via
for i in range(len(units) - 1):
for F in units:
for T in units:
if (F, T) not in rates:
for V in units:
if (F, V) in rates and (V, T) in rates:
rates[(F, T)] = rates[(F, V)] * rates[(V, T)]
inplst = [('10 cm', 'cm'), ('10 inch', 'mm'), ('1024 px', 'pt'), ('768 px', 'inch'), ('9144000 emu', 'inch'), ('12000 dxa', 'px')]
for p1, p2 in inplst:
p1 = p1.split()
print( int(p1[0]) * rates[(p1[1], p2)] )
그래프 문제로 이해했는데.. 그럴듯해 보이는 오답입니다(...) 문제를 잘못 이해했어요.
저 비율 계산하는 부분은 최단거리 알고리즘 중 하나를 흉내낸 건데, 보다시피 4중 반복문이라 가장 성능이 나쁜 대신 제약조건(싸이클, 음의 가중치 등)이 없습니다... 아니 없었던 거 같아요. 사실은 제일 단순한 게 장점.
이름은 잘 기억이 안 나네요.
[Python 3.6] 깊이 우선 탐색(depth-first search, DFS)
convArray = (
("inch", "cm", 2.54),
("cm", "mm", 10),
("inch", "pt", 72),
("inch", "px", 96),
("pt", "dxa", 20),
("dxa", "emu", 635),
("cm", "inch", 1/2.54),
("mm", "cm", 1/10),
("pt", "inch", 1/72),
("px", "inch", 1/96),
("dxa", "pt", 1/20),
("emu", "dxa", 1/635),
)
invited = []
resultConvRate = 1
def convertUnit(fromValueUnit, toUnit):
global invited, resultConvRate
fromValue, fromUnit = fromValueUnit.split()
invited = [fromUnit]
resultConvRate = 1
findConvRate(fromUnit, toUnit, 1)
print("{0}\t{1}\t{2} {3}".format(fromValueUnit, toUnit, str(float(fromValue) * resultConvRate), toUnit))
def findConvRate(fromUnit, toUnit, convRate):
global invited, resultConvRate
if fromUnit == toUnit:
resultConvRate = convRate
return
for convRateArray in convArray:
if convRateArray[0] == fromUnit and convRateArray[1] not in invited:
tmpConvRate = convRate * convRateArray[2]
invited.append(convRateArray[1])
findConvRate(convRateArray[1], toUnit, tmpConvRate)
fromValueUnit = "10 cm"
toUnit = "cm"
convertUnit(fromValueUnit, toUnit)
class Program
{
static double mm = 1;
static double inch = 25.4;
static double cm = 10;
static double pt = 25.4 / 72;
static double px = 25.4 / 96;
static double dxa = 25.4 / 72 / 20;
static double emu = 25.4 / 72 / 20 / 635;
static void Main(string[] args)
{
int value = int.Parse(Console.ReadLine());
string type = Console.ReadLine();
string transtype = Console.ReadLine();
double all = 0;
if (type == "cm")
{
all = value * cm;
}
else if (type == "inch")
{
all = value * inch;
}
else if (type == "pt")
{
all = value * pt;
}
else if (type == "px")
{
all = value * px;
}
else if (type == "dxa")
{
all = value * dxa;
}
else if(type == "emu")
{
all = value * emu;
}
if (transtype == "cm")
{
all = all / cm;
}
else if (transtype == "inch")
{
all = all / inch;
}
else if (transtype == "pt")
{
all = all / pt;
}
else if (transtype == "px")
{
all = all / px;
}
else if (transtype == "dxa")
{
all = all / dxa;
}
else if (transtype == "emu")
{
all = all / emu;
}
Console.WriteLine(all);
}
}
class Program
{
static double mm = 1;
static double inch = 25.4;
static double cm = 10;
static double pt = 25.4 / 72;
static double px = 25.4 / 96;
static double dxa = 25.4 / 72 / 20;
static double emu = 25.4 / 72 / 20 / 635;
static void Main(string[] args)
{
int value = int.Parse(Console.ReadLine());
string type = Console.ReadLine();
string transtype = Console.ReadLine();
double all = 0;
if (type == "cm")
{
all = value * cm;
}
else if (type == "inch")
{
all = value * inch;
}
else if (type == "pt")
{
all = value * pt;
}
else if (type == "px")
{
all = value * px;
}
else if (type == "dxa")
{
all = value * dxa;
}
else if(type == "emu")
{
all = value * emu;
}
if (transtype == "cm")
{
all = all / cm;
}
else if (transtype == "inch")
{
all = all / inch;
}
else if (transtype == "pt")
{
all = all / pt;
}
else if (transtype == "px")
{
all = all / px;
}
else if (transtype == "dxa")
{
all = all / dxa;
}
else if (transtype == "emu")
{
all = all / emu;
}
Console.WriteLine(all);
}
}
파이썬 3.6
"""
아이디어>
1) 입력 받은 source를 특정 단위 값으로 변환한 후
2) 해당 단위에서 target 단위(unit)로 변환합니다.
"""
def unittransform(source,unit):
result,tmp = 0,0
source_list = source.split(' ')
# source를 'inch' 값으로 변환 한 후
if source_list[1] == 'inch':
tmp = int(source_list[0])
elif source_list[1] == 'cm':
tmp = int(source_list[0])/2.54
elif source_list[1] == 'pt':
tmp = int(source_list[0])/72
elif source_list[1] == 'px':
tmp = int(source_list[0])/96
elif source_list[1] == 'dxa':
tmp = int(source_list[0])/(20*72)
elif source_list[1] == 'emu':
tmp = int(source_list[0])/(20*635*72)
# unit 값 단위로 변환
if unit == 'inch':
result = tmp
elif unit == 'cm':
result = tmp * 2.54
elif unit == 'mm':
result = 2.54 * tmp * 10
elif unit == 'pt':
result = tmp * 72
elif unit == 'px':
result = tmp * 96
elif unit == 'dxa':
result = tmp/(72*20)
elif unit == 'emu':
result = tmp/(72*20)* 635
print("%-10s %-10s %-10s"%(source,unit,str(int(result))+' '+unit))
if __name__ == "__main__":
source = input("source(ex> 10 cm) = ")
unit = input("unit = ")
unittransform(source,unit)
*결과값
10 cm cm 10 cm
10 inch mm 254 mm
1024 px pt 768 pt
768 px inch 8 inch
9144000 emu inch 10 inch
12000 dxa px 800 px
def change(n, a, b):
input_unit = {'inch' : 1, 'cm' : 1/2.54, 'mm' : 0.1/2.54, 'pt' : 1/72, 'px' : 1/96, 'dxa' : 1/(72*20), 'emu' : 1/(72*20*635)}
output_unit = {'inch' : 1, 'cm' : 2.54, 'mm' : 2.54*10, 'pt' : 72, 'px' : 96, 'dxa' : 72*20, 'emu' : 72*20*635}
return n*input_unit.get(a)*output_unit.get(b)
l = input().split()
print('{0} {1}'.format(change(float(l[0]), l[1], l[2]), l[2]))
import java.util.Scanner;
public class UnitChange {
public static double INCH = 1;
public static double CM = 2.54;
public static double MM = 25.4;
public static double PX = 96;
public static double PT = 72;
public static double DXA = 72 * 20;
public static double EMU = 72 * 20 * 635;
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
double num = sc.nextDouble();
String param1 = sc.next();
String param2 = sc.next();
switch(param1){
case "inch" :
num = num / INCH;
break;
case "cm" :
num = num / CM;
break;
case "mm" :
num = num / MM;
break;
case "px" :
num /= PX;
break;
case "pt" :
num /= PT;
break;
case "dxa" :
num /= DXA;
break;
case "emu" :
num /= EMU;
break;
}
switch(param2){
case "inch" :
num = num * INCH;
break;
case "cm" :
num = num * CM;
break;
case "mm" :
num = num * MM;
break;
case "px" :
num *= PX;
break;
case "pt" :
num *= PT;
break;
case "dxa" :
num *= DXA;
break;
case "emu" :
num *= EMU;
break;
}
System.out.println("param1\t\tparam2\t\tresult");
System.out.println("========================================");
System.out.printf("%s\t\t%s\t\t%s",(int)num + param1, param2, (int)num + param2);
}
}
// 단위 변환
package main
import (
"fmt"
"os"
)
var units map[string]float64
func initializeUnits() {
units = make(map[string]float64)
units["inch"] = 1.
units["cm"] = units["inch"] / 2.54
units["mm"] = units["cm"] / 10.
units["pt"] = units["inch"] / 72.
units["px"] = units["inch"] / 96.
units["dxa"] = units["pt"] / 20.
units["emu"] = units["dxa"] / 635.
}
func main() {
initializeUnits()
var factor float64
var from, to string
for {
factor = 0
fmt.Print("Input parameter1 [ex: 10 cm]: ")
fmt.Scanf("%f %s\n", &factor, &from)
if factor == 0 {
os.Exit(0)
}
fmt.Print("Input parameter2 [ex: mm]: ")
fmt.Scanf("%s\n", &to)
rst := cnv(factor, from, to)
fmt.Println(rst)
}
}
func cnv(factor float64, from, to string) string {
return fmt.Sprint(factor*units[from]/units[to]) + " " + to
}
Python
bf = ["1 inch", "1 cm", "1 inch", "1 inch", "1 pt", "1 dxa"]
af = ["2.54 cm", "10 mm", "72 pt", "96 px", "20 dxa", "635 emu"]
conv = {}
#모두 다 inch로 바꿀수 있으므로
for i in range(7):
if i == 0:
conv["inch"] = 1.0
else:
cur_unit = af[i-1].split(" ")[1]
transf = 1.0
while cur_unit != "inch":
for b, a in zip(bf, af):
if cur_unit == a.split(" ")[1]:
cur_unit = b.split(" ")[1]
transf *= float(a.split(" ")[0])
break
conv[af[i-1].split(" ")[1]] = transf
print(conv)
param1 = ["10 cm", "10 inch", "1024 px", "768 px", "9144000 emu", "12000 dxa"]
param2 = ["cm", "mm", "pt", "inch", "inch", "px"]
for p1, p2 in zip(param1, param2):
print("{0} to {1}: {2:.1f} {1}".format(p1, p2, float(p1.split(" ")[0])*conv[p2]/conv[p1.split(" ")[1]]))
def uconv(d1,d2):
for i in set(d1.keys()) & set(d2.keys()):
tmp = d1[i]/d2[i]
for j in d2:
d2[j] *= tmp
return dict(d1,**d2)
uc = [{'inch':1,'cm':2.54},
{'cm':1,'mm':10},
{'inch':1,'pt':72},
{'inch':1,'px':96},
{'pt':1,'dxa':20},
{'dxa':1,'emu':635}]
for i in uc:
if 'c' not in locals():
c = i
continue
c = uconv(c,i)
def conv(p1,p2,cd):
return str(float(p1.split()[0])*cd[p2]/cd[p1.split()[1]])+' '+p2
m = [('10 cm', 'cm'),
("10 inch", "mm"),
("1024 px", "pt"),
("768 px", "inch"),
("9144000 emu", "inch"),
("12000 dxa", "px")]
print('{:14}{:9}{:14}'.format('param1','param2','result'))
print('='*35)
for i in m:
print('{:14}{:9}{:14}'.format(i[0],i[1],conv(i[0],i[1],c)))
param1 param2 result
===================================
10 cm cm 10.0 cm
10 inch mm 254.0 mm
1024 px pt 768.0 pt
768 px inch 8.0 inch
9144000 emu inch 10.0 inch
12000 dxa px 800.0 px
C#
using System;
using System.Collections.Generic;
namespace CD021
{
class Program
{
static void Main(string[] args)
{
while (true)
{
Console.Write("첫 번째 인자 [예: 10 cm]: ");
string[] input1 = Console.ReadLine().Split();
if (input1[0] == "") { break; }
Console.Write("두 번째 인자 [예: inch]: ");
string input2 = Console.ReadLine();
var unit = new Units(double.Parse(input1[0]), input1[1], input2);
Console.WriteLine(unit.Converted);
}
}
}
class Units
{
private static readonly Dictionary<string, double> Unit = new Dictionary<string, double>();
static Units() // initialize static members (Unit)
{
Unit["inch"] = 1;
Unit["cm"] = Unit["inch"] / 2.54;
Unit["mm"] = Unit["cm"] / 10.0;
Unit["pt"] = Unit["inch"] / 72.0;
Unit["px"] = Unit["inch"] / 96.0;
Unit["dxa"] = Unit["pt"] / 20.0;
Unit["emu"] = Unit["dxa"] / 635.0;
}
private double originalValue;
private string originalUnit, targetUnit;
public Units(double originalValue, string originalUnit, string targetUnit)
{
this.originalValue = originalValue;
this.originalUnit = originalUnit;
this.targetUnit = targetUnit;
}
// 단위 변환된 문자열 반환
public string Converted
=> (originalValue * Unit[originalUnit] / Unit[targetUnit]).ToString() + " " + targetUnit;
}
}
op_table = {'inch':1,'cm':2.54,'pt':72,'px':96,'mm':25.4,'dxa':1440,'emu':91440}
temp_op1,op2 = input().split(',')
temp_num,op1 =temp_op1.split(' ')
num = int(temp_num)
result = num*(op_table[op2]/op_table[op1])
print('{0} {1}'.format(result,op2))
Java 8
createTree method 로 class Node 를 이용한 Tree 구조 설정.
각 단위들은 inch 로 변환한 배율을 저장하지 않고, Tree 구조 설정 시 Parent Node 와 현재 Node 의 배율을 Pair 객체에 저장.
getInchMag 으로 Param1 로 Inch 로 변환한 값을 저장.
3번에서 계산한 inch 값을 다시 Param2 단위로 계산.
package test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class tut01 {
// 배율을 구할 수 있는 전역변수 필요.
private static double toInchMag = 1;
private static double input1; // input1 : 입력 숫자
private static String input2; // input2 : 입력 수치
private static String input3; // input3 : 결과 수치.
// Factorial 을 멈출 기준이 필요.
private static boolean isExist = false;
// map 구성
private static HashMap<String, Node<String>> map = new HashMap<>();
private static Node<String> tree;
public static void main(String[] args) {
System.out.println("hello world");
// Node Tree 를 만든다.
createTree();
// 트리구조 확인. (Optional)
// printTree(tree, " ");
// 배율을 구해보자.
input1 = 10;
input2 = "cm";
input3 = "cm";
System.out.println(String.format("param1 %s / param2 %s / result %s",
input1 + " " + input2,
input3,
getResult(input1, input2, input3) + " " + input3));
input1 = 10;
input2 = "inch";
input3 = "mm";
System.out.println(String.format("param1 %s / param2 %s / result %s",
input1 + " " + input2,
input3,
getResult(input1, input2, input3) + " " + input3));
input1 = 1024;
input2 = "px";
input3 = "pt";
System.out.println(String.format("param1 %s / param2 %s / result %s",
input1 + " " + input2,
input3,
getResult(input1, input2, input3) + " " + input3));
input1 = 768;
input2 = "px";
input3 = "inch";
System.out.println(String.format("param1 %s / param2 %s / result %s",
input1 + " " + input2,
input3,
getResult(input1, input2, input3) + " " + input3));
input1 = 9144000;
input2 = "emu";
input3 = "inch";
System.out.println(String.format("param1 %s / param2 %s / result %s",
input1 + " " + input2,
input3,
getResult(input1, input2, input3) + " " + input3));
input1 = 12000;
input2 = "dxa";
input3 = "px";
System.out.println(String.format("param1 %s / param2 %s / result %s",
input1 + " " + input2,
input3,
getResult(input1, input2, input3) + " " + input3));
}
class Node<T> {
private T name = null;
private double magnification = 0;
private List<Node<T>> children = new ArrayList<>();
private Node<T> parent = null;
public Node(T data, double magnification) {
this.name = data;
this.magnification = magnification;
}
public Node<T> addChild(Node<T> child) {
child.setParent(this);
this.children.add(child);
return child;
}
public void addChildren(List<Node<T>> children) {
children.forEach(each -> each.setParent(this));
this.children.addAll(children);
}
public List<Node<T>> getChildren() {
return children;
}
public T getName() {
return name;
}
public void setData(T data) {
this.name = data;
}
private void setParent(Node<T> parent) {
this.parent = parent;
}
public Node<T> getParent() {
return parent;
}
public double getMagnification() {
return magnification;
}
}
private static <T> void printTree(Node<T> node, String appender) {
System.out.println(appender + node.getName());
node.getChildren().forEach(each -> printTree(each, appender + appender));
}
private static <T> void getInchMag(Node<T> node) {
toInchMag *= node.getMagnification();
if (node.getParent() != null) {
getInchMag(node.getParent());
}
}
private static <T> void getMagTaget(Node<T> node, String target) {
if (node.getChildren() != null) {
// zero 를 만들면 1로 초기화
toInchMag = node.getMagnification() == 0 ? toInchMag / toInchMag
: toInchMag * node.getMagnification();
for (Node<T> i : node.getChildren()) {
if (i.getName().equals(target)) {
toInchMag *= i.getMagnification();
isExist = true;
} else {
if (!isExist) {
getMagTaget(i, target);
}
}
}
}
}
private static void createTree() {
tut01 t = new tut01();
// Zero
Node<String> zero = t.new Node<String>("zero", 0);
map.put(zero.getName(), zero);
// inch
Node<String> inch = t.new Node<String>("inch", 1);
map.put(inch.getName(), inch);
// cm
Node<String> cm = t.new Node<String>("cm", 2.54);
map.put(cm.getName(), cm);
// mm
Node<String> mm = t.new Node<String>("mm", 10);
map.put(mm.getName(), mm);
// pt
Node<String> pt = t.new Node<String>("pt", 72);
map.put(pt.getName(), pt);
// dxa
Node<String> dxa = t.new Node<String>("dxa", 20);
map.put(dxa.getName(), dxa);
// emu
Node<String> emu = t.new Node<String>("emu", 635);
map.put(emu.getName(), emu);
// px
Node<String> px = t.new Node<String>("px", 96);
map.put(px.getName(), px);
// inch <= cm 자식으로 추가.
inch.addChild(cm);
// cm <= mm 자식으로 추가.
cm.addChild(mm);
// cm <= zero 자식으로 추가.
mm.addChild(zero);
// inch <= pt 자식으로 추가.
inch.addChild(pt);
// pt <= dxa 자식으로 추가.
pt.addChild(dxa);
// dxa <= emu 자식으로 추가.
dxa.addChild(emu);
// emu <= zero 자식으로 추가.
emu.addChild(zero);
// inch <= px 자식으로 추가.
inch.addChild(px);
// px <= zero 자식으로 추가.
px.addChild(zero);
// Tree 에 데이터 할당.
tree = inch;
}
private static double getResult(double param1, String param2, String param3) {
double result = 0;
// inch 로 변경.
getInchMag(map.get(param2));
double intermediate = input1 / toInchMag;
// 배율 초기화
toInchMag = 1;
isExist = false;
// 원하는 결과로 결과로 변경.
getMagTaget(tree, param3);
result = intermediate * toInchMag;
// 배율 초기화
toInchMag = 1;
return result;
}
}
def converse_unit(num, unit):
# 1 inch = 2.54 cm = 25.4 mm = 72 pt = 96 px = 1440 dxa = 914400 emu
ratio = {'inch':1, 'cm':2.54, 'mm':25.4, 'pt':72, 'px':96, 'dxa':1440, 'emu':914400}
unit_got = ''
num_seperated = 0
for find_unit in ratio.keys():
if find_unit in num:
unit_got = find_unit
num_seperated = float(num.split(find_unit)[0].strip())
conversed = num_seperated * ratio[unit] / ratio[unit_got]
if conversed == int(conversed):
conversed = int(conversed)
return '%s %s' %(conversed, unit)
print(converse_unit('12000 dxa', 'px'))
단위끼리의 비율을 일일히 구해 딕셔너리에 넣었습니다
import java.util.Scanner;
public class KimSanghyeop {
public static void main(String args[])
{
String[] name = {"inch","cm","mm","pt","px","dxa","emu"};
// 1 inch to change
double[] change = {1,2.54,2.54*10,72,96,72*20,72*20*635};
Scanner sc = new Scanner(System.in);
System.out.print("값을 입력하세요. : ");
String[] input_string = sc.nextLine().split(" ");
int input_num = Integer.valueOf(input_string[0]);
int input_type=0;
System.out.print("출력값은? : ");
String output_string = sc.nextLine();
int output_type=0;
for(int f1=0;f1<name.length;f1++)
{
if(name[f1].equals(input_string[1]))
{
input_type=f1;
}
if(name[f1].equals(output_string))
{
output_type=f1;
}
}
System.out.println(change[output_type] * input_num / change[input_type] + name[output_type]);
}
}
units = {'inch' : 1, 'cm' : 2.54,'mm' : 25.4, 'px' : 96, 'pt' : 72, 'dxa' : 72*20, 'emu' : 72*20*635}
def cunit(n,unit):
n = n.split()
return str(int(n[0])/units[n[1]]*units[unit]) + ' ' + unit
이게 맞는지 헷갈립니다.......
import re
UNIT_DICTIONARY = ['mm', 'cm', 'inch', 'pt', 'dxa', 'emu']
UNIT_RELA = ['(1/10)', '(1/(2.54))', '72', '20', '635', '1']
while True :
print("="*30+"Type \'QUIT\' to exit."+"="*30)
inp = input("INPUT : ")
if inp == 'QUIT' :
break
else :
TRANS_digits = re.compile("\d+")
TRANS_unit = re.compile("[a-zA-Z]+")
digits_BEFORE_TRANS = "".join(TRANS_digits.findall(inp))
unit_BEFORE_TRANS = "".join(TRANS_unit.findall(inp))
if unit_BEFORE_TRANS == 'px' :
unit_BEFORE_TRANS = 'inch'
digits_BEFORE_TRANS = '('+digits_BEFORE_TRANS+')'+'*(1/96)'
inp2nd = input("CONVERSE INTO : ")
pxON = 0
if inp2nd == 'px' :
inp2nd = 'inch'
pxON = 1
result = str(digits_BEFORE_TRANS)
if UNIT_DICTIONARY.index(inp2nd) < UNIT_DICTIONARY.index(unit_BEFORE_TRANS) :
for i in range(1, UNIT_DICTIONARY.index(unit_BEFORE_TRANS)-UNIT_DICTIONARY.index(inp2nd)+1) :
result = '('+result+')'+'/' + UNIT_RELA[UNIT_DICTIONARY.index(unit_BEFORE_TRANS)-i]
else :
for k in range(UNIT_DICTIONARY.index(unit_BEFORE_TRANS), UNIT_DICTIONARY.index(inp2nd)) :
result += '*' + UNIT_RELA[k]
if pxON == 1 :
result = '('+result+')'+'*96'
inp2nd = 'px'
pxON = 0
print(eval(result), inp2nd)
px를 제외하고는 단위간에 선형적인(?) 관계가 있다고 생각돼어 인접한 단위간의 관계를 이용하였습니다. px의 경우, inch로 변환해서 다른 단위로 고치거나, inch로 변환된 것을 px로 따로 바꾸는 식으로 만들었습니다. 제 실력의 한계를 확인할 수 있었던 문제였어요 ㅠㅠ
결과
==============================Type 'QUIT' to exit.==============================
INPUT : 768px
CONVERSE INTO : inch
8.0 inch
파이썬 3입니다.
각 단위의 inch에 대한 변환을 튜플에 저장한 다음, 입력값을 inch로 변환했다가 원하는 단위로 변환했습니다.
r, u1 = input().split()
u2 = input()
key = ('inch', 'cm', 'mm', 'pt', 'px', 'dxa', 'emu')
value = (1, 2.54, 25.4, 72, 96, 1440, 914440) # 1 inch = value key
out = float(r) * value[key.index(u2)] / value[key.index(u1)]
print('{0} {1}'.format(out, u2))
def conv(inp):
unit = {'inch': 1, 'cm': 2.54, 'mm': 25.4, 'pt': 72, 'px': 96, 'dxa': 1440, 'emu': 914400}
for n, i in enumerate(inp):
if n == 0:
x = int(i.split()[0]) / unit[i.split()[1]]
else:
result = unit[i] * x
print('{}\t\t{}\t\t{} {}'.format(inp[0], inp[1], result, inp[1]))
if __name__ == '__main__':
inp = ['12000 dxa', 'px']
conv(inp)
double의 범위를 무시하면 안된다는 교훈을 강하게 얻었다 그리고 이렇게 푸는건 너무 무식한거같다
import java.util.Scanner;
public class main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("바꾸고 싶은 값?");
String data = scan.nextLine();
String[] data1 = data.split(" ");
double data2 = Double.parseDouble(data1[0]);
System.out.println("바꾸려는 단위?");
String unit =scan.nextLine();
System.out.println("정답: "+ convert(data2,data1[1],unit));
}
public static String convert(double value,String unit1, String unit2) {
double[] toInch = {1, 1/2.54, 1/25.4, 0.013888, 0.0104, 0.000694, 0.000001094};//{inch, cm, mm, pt, px,dxa, emu}
double[] inchToOther = {1, 2.54, 25.4, 72, 96, (20*72), (20*72*635)};//{inch, cm, mm, pt, px,dxa, emu}
if(unit1.equals("inch"))
{
value = value*toInch[0];
System.out.println(value);
}
else if(unit1.equals("cm"))
{
value = value*toInch[1];
}
else if(unit1.equals("mm"))
{
value = value*toInch[2];
}
else if(unit1.equals("pt"))
{
value = value*toInch[3];
}
else if(unit1.equals("px"))
{
value = value*toInch[4];
}
else if(unit1.equals("dxa"))
{
value = value*toInch[5];
}
else
{
value = value*toInch[6];
}
if(unit2.equals("inch"))
{
value = value*inchToOther[0];
return (value+" inch");
}
else if(unit2.equals("cm"))
{
value = value*inchToOther[1];
return (value+" cm");
}
else if(unit2.equals("mm"))
{
value = value*inchToOther[2];
return (value+" mm");
}
else if(unit2.equals("pt"))
{
value = value*inchToOther[3];
return (value+" pt");
}
else if(unit2.equals("px"))
{
value = value*inchToOther[4];
return (value+" px");
}
else if(unit2.equals("dxa"))
{
value = value*inchToOther[5];
return (value+" dxa");
}
else
{
value = value*inchToOther[6];
return (value+" emu");
}
}
}
def unit(p, q):
d = int(p.split(" ")[0])
u = p.split(" ")[1]
unitArr = ["cm", "mm", "pt", "px", "dxa", "emu", "inch"]
dArr = [2.54, 25.4, 72, 96, 1440, 914400, 1]
for i in unitArr:
if u == i:
temp = d / dArr[unitArr.index(i)]
for i in unitArr:
if q == i:
result = round(temp * dArr[unitArr.index(i)],5)
print(str(result) +" "+ q)
def cross(b,q):
inch = {"cm" : 2.54, "pt" : 72, "px" : 96}
cm = {"mm": 10 }
pt = {"dxa": 20 }
dxa = {"emu": 635}
if b in inch:
c= inch[b]*q # 인치 속 단위의 수와 변환하고자 하는 수를 곱해줌
print(c,b)
elif b=="inch":
print(q,b)
elif b in cm:
c = cm[b]*q*inch["cm"]
print(c,b)
elif b in pt:
c = pt[b]*q*inch["pt"]
print(c,b)
elif b in dxa:
c = dxa[b]*q*pt["dxa"]*inch["pt"]
print(c,b)
def unit():
A = input("변환 할 수를 입력하세요 : ")
b = input("변환 할 단위를 입력하세요 : ")
a = A.split() #a[0] 숫자 a[1] 단위
inch = {"inch":int(a[0]),"cm":int(a[0])/2.54, "mm":int(a[0])/25.4, "px":int(a[0])/96, "pt":int(a[0])/72, "dxa":int(a[0])/1440, "emu":int(a[0])/914400}
q = inch[a[1]]
cross(b,q)
unit()
print('='*8,'입력형식 : Nsign , sign','='*8)
before,sign = input('입력 : ').split()
n = ''.join([_ for _ in before if _.isdigit()])
bsign = ''.join([_ for _ in before if _.isalpha()])
#inch기준 단위별 값
sign_list = [ 'cm' , 'mm' ,'inch' , 'px' , 'pt' , 'dxa' , 'emu']
sign_n = [ 2.54 , 25.4 , 1 , 96 , 72 , 72*20 , 72*20*635 ]
a = sign_list.index(bsign)
b = sign_list.index(sign)
result = int(n)/(sign_n[a])*sign_n[b]
print(f'{result} {sign}')
// Rust
// recursive function
fn main() {
unit_conversion("10 cm cm");
unit_conversion("10 inch mm");
unit_conversion("1024 px pt");
unit_conversion("768 px inch");
unit_conversion("9144000 emu inch");
unit_conversion("12000 dxa px");
} use std::collections::HashMap; fn unit_conversion(input: &str) {
let mut iter = input.split_whitespace();
let d: f64 = iter.next().unwrap().parse().unwrap();
let u1 = iter.next().unwrap();
let u2 = iter.next().unwrap();
let result = if u1 == u2 { d }
else { d * find_conversion(u1, u2)};
println!("{:?} {}", result, u2);
} fn find_conversion(u1: &str, u2: &str) -> f64 {
let mut map = HashMap::new();
map.insert(("inch", "cm"), 2.54);
map.insert(("cm", "mm"), 10.);
map.insert(("inch", "pt"), 72.);
map.insert(("pt", "dxa"), 20.);
map.insert(("dxa", "emu"), 635.);
map.insert(("inch", "px"), 96.);
for (k, v) in map {
if k == (u1, u2) { return v;}
else if k == (u2, u1) { return 1./v; }
else if k.0 == u1 { return v * find_conversion(k.1, u2); }
else if k.1 == u1 { return 1./v * find_conversion(k.0, u2);}
}
0.
}
파이썬입니다. 일단 주어진 단위들 중 inch가 가장 큰 단위여서 1 inch = 2.54cm = 25.4mm ...등으로 해서 처음 받은 인수가 inch면 그대로 하고 만약 다른 인수이면 일단 inch로 바꾸어준 다음 다시 실행하는 재귀함수를 이용해봤습니다
def UnitTransform(a,b):
a = a.split()
if a[1] == "inch":
if b == "cm":
a[0] = str(float(a[0])*2.54)
a[1] = "cm"
return a[0] + " " + a[1]
elif b == "mm":
a[0] = str(float(a[0])*25.4)
a[1] = "mm"
return a[0] + " " + a[1]
elif b == "pt":
a[0] = str(float(a[0])*72)
a[1] = "pt"
return a[0] + " " + a[1]
elif b == "px":
a[0] = str(float(a[0])*96)
a[1] ="px"
return a[0] + " " + a[1]
elif b == "dxa":
a[0] = str(float(a[0])*1440)
a[1] = "pt"
return a[0] + " " + a[1]
elif b == "emu" :
a[0] = str(float(a[0])*914400)
a[1] = "emu"
return a[0] + " " + a[1]
else:
return a[0] + " " + a[1]
elif a[1] == "cm":
a[0] = str(float(a[0])/2.54)
a[1] = "inch"
a = a[0] + " " + a[1]
return UnitTransform(a,b)
elif a[1] == "pt":
a[0] = str(float(a[0])/72)
a[1] = "inch"
a = a[0] + " " + a[1]
return UnitTransform(a,b)
elif a[1] == "dxa":
a[0] = str(float(a[0])/1440)
a[1] = "inch"
a = a[0] + " " + a[1]
return UnitTransform(a,b)
elif a[1] == "px":
a[0] = str(float(a[0])/96)
a[1] = "inch"
a = a[0] + " " + a[1]
return UnitTransform(a,b)
elif a[1] == "emu":
a[0] = str(float(a[0])/914400)
a[1] = "inch"
a = a[0] + " " + a[1]
return UnitTransform(a,b)
elif a[1] == "mm":
a[0] = str(float(a[0])/25.4)
a[1] = "inch"
a = a[0] + " " + a[1]
return UnitTransform(a,b)
print(UnitTransform("10 cm","cm"))
unit_value = {'inch':1, 'cm':2.54, 'mm':2.54*10, 'pt':72, 'px':96, 'dxa':72*20, 'emu':72*20*635}
def unit_transfomation(param1, param2):
value, unit = param1.split()
print(' \"%-12s\" \"%-4s\" \"%d %s\" ' %(param1, param2, float(value)*unit_value[param2]/unit_value[unit], param2))
print(' param1 param2 result')
print('==================================')
unit_transfomation("10 cm", "cm")
unit_transfomation("10 inch", "mm")
unit_transfomation("1024 px", "pt")
unit_transfomation("768 px", "inch")
unit_transfomation("9144000 emu", "inch")
unit_transfomation("12000 dxa", "px")
JAVA입니다. 해당 사례 외에 다른 단위가 더 추가되고 상호 변환 관계가 복잡해지더라도 이를 반영할 수 있는 코드를 작성하였습니다.
package question2.단위_변환;
import java.util.ArrayList;
import java.util.List;
public class ConversionFinder {
static List<UnitConvert> conversions = new ArrayList<UnitConvert>();
//단위 간 변환율 저장
public ConversionFinder() {
}
static void initiate() {
conversions.add(new UnitConvert("inch", "cm", 2.54));
conversions.add(new UnitConvert("cm", "mm", 10.0));
conversions.add(new UnitConvert("inch", "pt", 72.0));
conversions.add(new UnitConvert("inch", "px", 96.0));
conversions.add(new UnitConvert("pt", "dxa", 20.0));
conversions.add(new UnitConvert("dxa", "emu", 635));
}
static double findPath(double value, String start, String end, List<String> visited) {
//단위 변환 경로를 찾은 후 변환한 값을 반환하는 재귀함수
//value: 변환하려는 값, start: 시작 단위, end: 끝 단위
//visited: 이미 선택한 시작 단위를 배제하여 두 단위 사이를 무한히 오가는 stackOverFlow 방지
for (UnitConvert uc : conversions) {
double result = uc.convert(start);
if(result != 0 && !visited.contains(uc.start)) {
//start에서 이동할 수 있는 경로이며 이전에 간 경로가 아님
List<String> newVisited = new ArrayList<String>();
newVisited.addAll(visited);
if(uc.start.equals(start)) {
//정방향->uc의 start가 실제 경로의 start인 경우
newVisited.add(uc.start);
if(uc.end.equals(end)) {
return value * result; //변환율을 곱함
}
result = findPath(value * result, uc.end, end, newVisited);
//다른 변수를 정의하기 귀찮아서 result를 다시 사용함
}
else {
//역방향->uc의 start가 실제 경로에서는 end인 경우
newVisited.add(uc.end);
if(uc.start.equals(end)) {
return value / result; //변환율의 역수를 곱함
}
result = findPath(value / result, uc.start, end, newVisited);
}
if(result != 0) {
//result가 0인 경우는 연결되는 경로가 없다는 의미
return result;
}
}
}
return 0;
}
}
package question2.단위_변환;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
String param = sc.nextLine();
double value = Double.parseDouble(param.split(" ")[0]);
String start = param.split(" ")[1];
String end = sc.nextLine();
ConversionFinder.initiate();
double result = ConversionFinder.findPath(value, start, end, new ArrayList<String>());
System.out.println(result + " " + end);
}
}
package question2.단위_변환;
public class UnitConvert {
//한 단위에서 다른 단위로의 변환율을 저장하는 클래스
String start; //시작 단위
String end; //끝 단위
double multiply; //변환율
public UnitConvert(String start, String end, double multiply) {
this.start = start;
this.end = end;
this.multiply = multiply;
}
double convert(String type) {
if(type.equals(start) || type.equals(end)) {
return multiply; //시작 또는 끝과 같은 경우 변환율 반환
}
return 0; //시작에도, 끝에도 없는 경우 0 반환
}
}