1.   Math Expression Parser 비교

 

1.1 DataTable

.Net에서 제공하는 DataTable Class Compute 메서드를 이용해 식을 계산한 코드이다. 먼저 a, b 문자를 값으로 치환한 후 계산을 진행한다. Compute 메서드의 반환값은 object로써 type에 맞게 캐스팅 해주어야하는 단점이 있다. 테스트는 아래와 같이 진행하였다.

object res = null;
DataTable dt = new DataTable();
 
 
string exp = expression;
foreach (KeyValuePair<stringstring> item in values)
{
    exp = exp.Replace(item.Key, item.Value);
}
 
Stopwatch st = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
    res = dt.Compute(exp, null);
    Type type = res.GetType();
 
    if (type == typeof(int))
    {
        int a = (int)res;
    }
    else
    {
        double b = (double)res;
    }
}
st.Stop();
Console.WriteLine(string.Format("DataTable = {0} : {1}", st.Elapsed.ToString(), res.ToString()));

 

1.2 Ncalc

CodePlex에 등록되어 있는 오픈소스로써 System.Math 클래스의 메서들과 사용자 정의 함수를 지원한다. 사용자 정의 함수는 이벤트 방식으로 함수명으로 비교해서 개발자가 직접 처리를 해주어야 한다.

Debug.Assert(0 == new Expression("Sin(0)").Evaluate());

  Debug.Assert(2 == new Expression("Sqrt(4)").Evaluate());

Debug.Assert(0 == new Expression("Tan(0)").Evaluate());

 

//함수 처리

Expression e = new Expression("SecretOperation(3, 6)");

  e.EvaluateFunction += delegate(string name, FunctionArgs args)

      {

          if (name == "SecretOperation")

              args.Result= (int)args.Parameters[0].Evaluate() + (int)args.Parameters[1].Evaluate();

      };

  Debug.Assert(9 == e.Evaluate());

 

테스트는 아래와 같이 진행하였다.

object res = null;
NCalc.Expression ex = new NCalc.Expression(expression);
 
ex.Parameters.Clear();
 
Dictionary<stringobject> v = new Dictionary<stringobject>();
 
foreach (KeyValuePair<stringstring> item in values)
{
    ex.Parameters.Add(item.Key, Convert.ToSingle(item.Value));
}
 
Stopwatch st = Stopwatch.StartNew();
 
 
for (int i = 0; i < 100000; i++)
{
    res = ex.Evaluate();
}
 
st.Stop();
Console.WriteLine(string.Format("NCalc = {0} : {1}", st.Elapsed.ToString(), res.ToString())); 

 

1.3 Flee

CodePlex에 등록되어 있는 오픈 소스로써 Fast Lightweight Expression Evaluator라는 이름과 같이 테스트한 오픈소스 중에서는 가장 빠르다. System.Math Class 및 타 Class를 등록해서 사용 할 수있고, 사용자 정의 함수 기능을 제공한다. 사용자 정의 함수는 문자열로 정의 할 수 있지만, 매개변수가 바뀔시 Recalculate라는 메서드를 호출하여 엔진 내부를 수정 해야 하는 문제가 있다.

 

// 함수 테스트
CalculationEngine engine = new CalculationEngine();
ExpressionContext context = new ExpressionContext();
 
 
context.Variables.Add("a", 2);
context.Variables.Add("b", 2);
 
engine.Add("Func1""(a*b) + 2.0", context);
 
 
Stopwatch st = Stopwatch.StartNew();
double res = 0;
for (int i = 0; i < 800; i++)
{
    res = engine.GetResult<double>("Func1");
    context.Variables["a"] = 3;
    engine.Recalculate("Func1");
}
st.Stop();
Console.WriteLine(string.Format("FleeFunc = {0} : {1}", st.Elapsed.ToString(), res.ToString()));

 

테스트는 아래와 같이 진행하였다.

ExpressionContext context = new ExpressionContext();
 
double res = double.NaN;
 
context.Variables.Clear();
            
foreach (KeyValuePair<stringstring> item in values)
{
    context.Variables[item.Key] = Convert.ToDouble(item.Value);
}
 
IGenericExpression<double> exp = context.CompileGeneric<double>(expression);
 
Stopwatch st = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
    res = exp.Evaluate();
}
st.Stop();
Console.WriteLine(string.Format("Flee = {0} : {1}", st.Elapsed.ToString(), res.ToString()));

 

1.4 MathParseNet

CodeProject에 등록되어 있는 오픈 소스로써 sin, cos, tg, ctg 등 기본적인 수학 함수를 제공한다. 식의 해석과 동시에 값을 반환하는 형식이여서 오픈 소스 중에 가장 느렸고, 반환 값의 타입은 int, double 두개의 타입만 존재한다.

MathParserNet.Parser parser = new MathParserNet.Parser();
 
double res = double.NaN;
parser.RemoveAllVariables();
 
foreach (KeyValuePair<stringstring> item in values)
{
    parser.AddVariable(item.Key, item.Value);
}
 
Stopwatch st = Stopwatch.StartNew();
 
for (int i = 0; i < 100000; i++)
{
    MathParserNet.SimplificationReturnValue ret = parser.Simplify(expression);
    if (ret.ReturnType == MathParserNet.SimplificationReturnValue.ReturnTypes.Integer)
    {
        res = ret.IntValue;
    }
    else
    {
        res = ret.DoubleValue;
    }
}
st.Stop();
Console.WriteLine(string.Format("MathParseNet = {0} : {1}", st.Elapsed.ToString(),res.ToString()));

 

 

 

1.5  테스트

  컴파일 모드 : Release

테스트한 식 : (a * b) / 2 + 3 - 2 * 321

테스트 값 : float a = 2, float b = 3

호출 테스트 수 : 100,000

 

테스트 결과:

CSharp

Lambda

DataTable

Ncalc

Flee

MathParseNet

Test1

0.000352

0.000498

0.433453

0.205334

0.017759

14.45983

Test2

0.000259

0.0005

0.350152

0.204596

0.017735

14.61664

Test3

0.00028

0.000492

0.34059

0.154331

0.017455

14.54161

Test4

0.000243

0.000489

0.339338

0.154261

0.017464

14.52951

Test5

0.000251

0.000552

0.3525

0.206181

0.018056

14.5986

평균

0.000277

0.000506

0.363207

0.184941

0.017694

14.54924

CSharp 기준(배수)

1

1.827653

1311.215

667.656

63.87588

52524.33

3 Parser 테스트 결과

 

1.6 결론

Flee 오픈소스가 가장 빠르지만, CSharp으로 하드코딩한 연산에 비해 63배나 느렸다. Parser들은 속도에 민간한 프로젝트에 적용하기는 힘들 것 같다.

 

 

프로젝트 :AboutCalculParser.zip

 

 

C# Excel 2007 추가기능(AddIn) 만들기

 

엑셀 리본 컨트롤에 새로운 탭을 만들어서, 사용자가 선택한 셀들의 합과 평균을 메시지 창에 보여주는 작업을 진행하겠습니다.

 

 

 

우선 프로젝트를 하나 생성하겠습니다. 설치된 테블릿에서 Office를 선택후 Excel 2007 추가 기능을 선택 후 솔루션 이름을 “AboutExcelAddIn”으로 생성합니다.

 

 

 

생성 후 프로젝트에서 오른쪽 마우스를 클릭하여 새 항목 추가를 클릭합니다. 리본(비주얼 디자이너)를 선택하여 생성합니다.

 

 

 

리본을 생성 후에 솔루션 탐색기를 확인해보시면 아래와 같습니다.

 

 

 

 

먼저 Ribbon1.cs를 클릭합니다. 아래의 이미지와 같이 ButtonGroup Sum, Avg Button을 생성합니다.

 

 

Sum Name btnSum, Avg Name btnAvg로 지정합니다. 더블 클릭하여 버튼이 클릭이 되었을 때 이벤트들을 등록합니다.

 

ThisAddIn 코드를 보시면 기본적으로 아래와 같은 코드가 자동으로 추가되어 있는 것을 확인하실수 있습니다.

 

namespace AbooutExcelAddIn
{
    public partial class ThisAddIn
    {
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            
        }
 
        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
           
        }
 
        #region VSTO generated code
 
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }
        
        #endregion
    }
}

 

 

Ribbon 개체를 생성 후 Sum Avg 버튼에 대한 Click 이벤트를 등록하였습니다. Application 개체를 통해서 Excel에 액세스 할 수 있습니다. 아래의 코드에서는 사용자가 선택한 Cell들을 가져오는 작업을 진행하였습니다. dynamic이기 때문에 Intelligence를 확인 하실 수 없습니다. 구글링을 통해 API를 검색하시거나 디버깅해서 어떤 값들이 있는지 확인하셔야 합니다.

 

 

using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Office.Tools.Ribbon; using Excel = Microsoft.Office.Interop.Excel; using Microsoft.Office.Interop.Excel; namespace AbooutExcelAddIn {     public partial class Ribbon1     {         void btnAvg_Click(object sender, RibbonControlEventArgs e)         {             double sum = 0;             int count = 0;             Application app = Globals.ThisAddIn.Application;             foreach (var item in app.Selection.Cells)             {                 string text = item.FormulaLocal;                 double value = 0;                 if (double.TryParse(text, out value))                 {                     sum += value;                     count++;                 }             }             double avg = sum / count;             System.Windows.Forms.MessageBox.Show(avg.ToString());         }         void btnSum_Click(object sender, RibbonControlEventArgs e)         {             double sum = 0;             Application app = Globals.ThisAddIn.Application;             foreach (var item in app.Selection.Cells)             {                 string text = item.FormulaLocal;                 double value = 0;                 if (double.TryParse(text, out value))                     sum += value;             }             System.Windows.Forms.MessageBox.Show(sum.ToString());         }     } } 

Ribbon을 추가하는 작업을 하지 않았는데, 어떻게 추가되었는지 궁금하신분들은, Ribbon Designer Class를 확인해보시면 답이나옵니다.

 

 

완료되었습니다. 컴파일을 진행 하신후 실행하게 되면 아래와 같이 동작하는 Excel 추가기능을 작성하신겁니다.

 

 

 

Excel 옵션->추가 기능에 가보시면 작성한 추가 기능이 등록된 것을 확인 할 수 있습니다.

 

 

 

프로젝트 파일 :

AbooutExcelAddIn.zip

 

결혼하는데 첫단계라고 하는

상견례를 마쳤어요

굿모닝

 

 

저희 집은 일산이고

남자친구 집은 군포라~~

 

중간지점인 영등포에 위치한

선유한정식에 예약을 했어요

 

 

상견례 자리라.. 사진을 못찍어서

선유한정식 홈페이지에서

캡쳐해왔어요...ㅠㅠ

 

 

저희는 선유 스페셜 D로

8명 예약했습니다.

 

상견례 전날 부터 엄청 떨려서

잠도 설쳤는데....

 

다행히 양가 부모님들께서 편하게 해주셔서

무사히 잘 끝냈 수 있었던거 같아용

하트3

 

 

처음에 단호박죽 이랑 백김치가 셋팅 됐었고

다먹기 전에 샐러드, 계절냉채(해파리냉채), 탕평채, 궁중 잡채,

쭈꾸미 볶음, 생선회, 연어크레페(?), 삼색전, 불고기가 나왔어요~~

 

저희 아빠가 회를 좋아하셔서

남자친구가 회를 따로 주문해서 크게

한접시가 따로 나왔어요~

 

추가 주문한 회는 3만원이였네용

 

다먹어 갈때쯤 계절탕(조랭이떡에 멸치육수? 약간 비린맛), 생선튀김,

제육보쌈, 황태구이, 버섯탕수육이 나와서

먹을 음식이 줄서 있었죠

 

열심히 먹고 있을 무렵

진지 드릴까요? 라고 물으셔서

네~라고 하니

밥, 된장찌개, 굴비구이, 미나리나물, 건새우볶음, 장조림, 김치

이렇게 셋팅되었어요.

 

 

후식으론 수박과 오미자차가 나왔어요~

후식을 서빙해 주시던 분이

원래 서빙해 주시던 분이 아니라

주방에서 일하시는 분이 급하게 나오신것 같았어요..

 

그래서 그런지...

오미자차를 주시다가 제 등에 촤악~!!ㅠㅠ

 

기분 좋게 마무리 하고 싶었으나...

마지막에 그런일이 있었네요 ㅜㅜ

 

상견례 자리라... 화도 못내고...

괜찮다고 했네요;;;ㅋㅋ

 

음식들은 어떤 맛이었는지 정확히 기억이 나진 않앗지만

대체적으로 SoSo~

 

아무튼 상견례를 잘 맞친것 같아

기분 좋게 하루를 보냈네요

홧팅2

 

 

'♡Wedding♥' 카테고리의 다른 글

[D-168] 허니문 예약(발리)  (0) 2014.08.09
[D-141] 오르시아에서 예물 맞췄어용  (0) 2014.08.09

지난주 토요일

오픈프라이즈 앱에서 당첨된

미아베라 주얼리카페에 다녀왓어요

 여행

 

 

미아베라는 신사에 위치해 있고

건물 1층에서 카페를 운영하고

위층들은 주얼리 디자인 회사라고 해요~

 

 

 

외부 모습이 깔끔하고

귀엽게 꾸며져 있었어요 ㅋㅋ

 

 

 

 

내부 모습은 아늑하면서도

 주얼리 카페라는

이름만큼

블링블링한 주얼리들이

진열되어 있더라구요~~ 

 

 

 

 

이렇게 블로그에 올려도

되는건지... 모르겠지만

일단.. 올리도록...

 

 

 

디자인 때문에

문제가 발생한다면...말씀해주세요

내리겠습니다.

응응

 

 

 

테이블이 몇개 없어서

더 아늑해 보이기도 하는 것 같아요

 

 

 

 

미아베라가 나의봄 이라는 뜻이래용ㅋㅋ

미아베라 소개가 써있는

뒷쪽엔 각종 술 메뉴들이~~ㅋㅋ

 

 

 

 

안주류가 눈에 확 들어왔지만

우린 쿠폰으로 먹어야 하니까~~

 

 

주문하러 카운터에 가면

메뉴가 붙어있어용ㅋㅋㅋ

 

제가 당첨된 쿠폰은

피자 + 건강 샐러드 + 빙수

쿠폰이여서

피자와 빙수를 선택할 수 있어요

 

피자는 핫 칠리 쉬림프 피자

빙수는 망고 빙수로 주세요~~

샤방

 

 

주문을 하면 얼마 안지나

건강 샐러드와 기본 세팅을

해줍니다.ㅋㅋ

 

 

 

맛있겠죠?

닭가슴살도 약간 들어있고

치즈, 달걀, 올리브, 야채, 토마토가

들어있어요 ㅋㅋ

 

 

 

 

전 평소 올리브를 좋아하지

않는 편인데

건강 샐러드에 들어가 있는건

맛이 괜찮더라구요

 

발사믹 소스때문인가??

 

 

 

 

샐러드를 흡입하고 있으면

주문한 피자가 나와요~~

 

그렇게 안매워 보이죠?

한입 먹는 순간 핫이 맞구나 싶었어요 ㅋㅋ

 

저희는 평소 매운걸 좋아해서 그렇게 맵다고

느끼진 못했지만 매운향이 나요

 

남자친구는 먹다가

피자에서 고추장 맛이 난다고....ㅋㅋ

 

 

 

 

물만 마시려 했지만

피자 먹다보니 음료가 땡겨서

레몬에이드 한잔 주문했어요

 

가격이 7000원 씩이나 하는 레몬에이드...

 

빙수가 있다는걸 잊은채 주문후에

후회했어요....ㅠㅠ

 

 

 

 

짜잔~~ 그래도 7000원 값은 하는것 같죠?

일반 카페에서 파는 가루 레몬에이드가 아닌

진짜 레몬으로 만든거 였어요

 

먹으면서 달지 않아 마음에 들었어요

오키

 

 

마지막으로 망고 빙수!!

위의 초콜렛은 너무 달아

먹는 걸 포기 했어요....

 

망고는 생망고와 그냥 망고 맛 과일 같은게

섞여 있어요

 

생망고는 제 입맛에 안 맞아서...

 

결국 반 이상 남기고 왔어요..ㅜㅜ

 

그래도 쿠폰으로 먹어 이렇게 많은 음식을

7000원에 먹었네요>.<

 

건강 샐러드는 정말정말 강추!!

 

서비스와 직원의 태도가 정말 맘에 드는 카페였어요

HAAA

 

 

WinAPI QueryPerformanceCounter 함수와 Stopwatch 클래스를 이용해 두가지 버젼으로 구현하였다.

 

 

 

 

usSleep.zip

 

 

 

 

QueryPerformanceCounter를 이용한 us Sleep

 

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Threading;
 
namespace Some
{
    public class Sleep
    {
        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
 
        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceFrequency(out long lpFrequency);
 
        private static long freq;
        private static double ufreq;
        private static double mfreq;
 
        static Sleep()
        {
            if (QueryPerformanceFrequency(out freq) == false)
            {
                throw new Win32Exception();
            }
            ufreq = freq / 1000000;
            mfreq = freq / 1000;
        }
 
        public Sleep()
        {
            USleep(0);
        }
 
        public void USleep(double us)
        {
            long startTime = 0;
            long nowTime = 0;
 
            QueryPerformanceCounter(out startTime);
 
            while (((nowTime - startTime) / ufreq) < us)
            {
                QueryPerformanceCounter(out nowTime);
            }
        }
 
        public void MSleep(double ms)
        {
            long startTime = 0;
            long nowTime = 0;
 
            QueryPerformanceCounter(out startTime);
 
            while (((nowTime - startTime) / mfreq) < ms)
            {
                QueryPerformanceCounter(out nowTime);
            }
        }
    }
}

 

 

 

 

 

Stopwatch Class를 이용한 us Sleep

 

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
 
namespace Some
{
    class SWSleep
    {
        long freq = 0;
        public SWSleep()
        {
            this.freq = Stopwatch.Frequency;
            USleep(0);
        }
 
        internal void USleep(int us)
        {
            double sec = (double)us / 1000000;
            Stopwatch sw = Stopwatch.StartNew();
            while (sw.ElapsedTicks / (double)freq < sec)
            {
            }
        }
 
        internal void MSleep(int ms)
        {
            double sec = (double)ms / 1000;
            Stopwatch sw = Stopwatch.StartNew();
            while (sw.ElapsedTicks / (double)freq < sec)
            {
            }
        }
    }
}

 

QueryPerformanceCounter, QueryPerformanceFrequency를 이용하여

 

ms, us 단위의 Sleep 함수 구현하였다.

 

 

Sleep.zip

 

 

 

main.c

 

 

#include "Sleep.h"
#include <stdio.h>
 
 
void main()
{
	int i=0;
	if(InitSleep() == 0)
	{
		printf("Error\n");
		return;
	}
 
	printf("Start");
	USleep(1000000);
	printf("Stop");
}

 

 

 

Sleep.c

 

 

#include "Sleep.h" static LARGE_INTEGER freq; static long ufreq; static long mfreq; int InitSleep() { if (QueryPerformanceFrequency(&freq) == 0) { return 0; } ufreq = freq.QuadPart / 1000000; mfreq = freq.QuadPart / 1000; return 1; } void USleep(double us) { LARGE_INTEGER startTime; LARGE_INTEGER nowTime; memset(&startTime,0,sizeof(LARGE_INTEGER)); memset(&nowTime,0,sizeof(LARGE_INTEGER)); QueryPerformanceCounter(&startTime); while (((nowTime.QuadPart - startTime.QuadPart) / ufreq) < us) { QueryPerformanceCounter(&nowTime); } } void MSleep(double ms) { LARGE_INTEGER startTime; LARGE_INTEGER nowTime; memset(&startTime,0,sizeof(LARGE_INTEGER)); memset(&nowTime,0,sizeof(LARGE_INTEGER)); QueryPerformanceCounter(&startTime); while (((nowTime.QuadPart - startTime.QuadPart) / mfreq) < ms) { QueryPerformanceCounter(&nowTime); } }

 

 

Sleep.h

 

 

#include <Windows.h>
 
int InitSleep();
void USleep(double us);
void MSleep(double ms);

 

 

 

 

 

 

구현 코드:

 

 

#include <stdio.h> #include <stdlib.h> #include <string.h> #define OUT_FILE_NAME "output.txt" #define INPUT_FILE_NAME "input.txt" void ReadInput(int *len, int *type); void WriteOutput(char *text); void RemoveOutput(); void ProcType1(int len); void ProcType2(int len); void ProcType3(int len); int main() { int len =0, type=0; void (*ProcTypeFn[4])(int); ProcTypeFn[1] = ProcType1; ProcTypeFn[2] = ProcType2; ProcTypeFn[3] = ProcType3;      RemoveOutput(); ReadInput(&len, &type); if((type >= 1 && type <= 3) && (len > 0 && len <=100)) { ProcTypeFn[type](len); } else { WriteOutput("INPUT ERROR!"); } return 0; } void ProcType1(int len) { //* //** //*** //**** //***** int i=0,j=0; for(i=1;i<=len;i++) { for(j=0;j<i;j++) { WriteOutput("*"); } WriteOutput("\n"); } } void ProcType2(int len) { //***** //**** //*** //** //* int i=0,j=0; for(i=len;i>0;i--) { for(j=0;j<i;j++) { WriteOutput("*"); } WriteOutput("\n"); } } void ProcType3(int len) { //    *    //4 //   ***   //3 //  *****  //2 // ******* //1 //********* int i=0,j=0,k=0; for(i=1;i<=len;i++) { for(j=len-i;j>0;j--) { WriteOutput(" "); } for(k=0;k<(i*2)-1;k++) { WriteOutput("*"); } WriteOutput("\n"); } } void RemoveOutput() { unlink(OUT_FILE_NAME); } void WriteOutput(char *text) { FILE* fs; char *res=0; fs=fopen(OUT_FILE_NAME,"a"); if(fs) { while(*text != '\0') { fwrite(text, 1, 1, fs); text++; } fclose(fs); } } void ReadInput(int *len, int *type) { FILE* fs; char data[100]={0}; char *res=0; fs=fopen(INPUT_FILE_NAME,"r"); if(fs) { fread(data, sizeof(char),5,fs); *len = atoi(strtok(data, " ")); *type = atoi(strtok(0, " ")); fclose(fs); } }

 

 

 

구현 코드:

 

 

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

#define OUT_FILE_NAME "output.txt"

#define INPUT_FILE_NAME "input.txt"

 

void ReadInput(int *len, int *type);

void WriteOutput(char *text);

void RemoveOutput();

 

void ProcType1(int len);

void ProcType2(int len);

void ProcType3(int len);

 

 

int main()

{

          int len =0, type=0;

 

          void (*ProcTypeFn[4])(int);

          ProcTypeFn[1] = ProcType1;

          ProcTypeFn[2] = ProcType2;

          ProcTypeFn[3] = ProcType3;    

 

          RemoveOutput();

          ReadInput(&len, &type);

 

          ProcTypeFn[type](len);

         

          return 0;

}

 

void ProcType1(int len)

{

          //한변의 길이 len 정사각형을 아래와 같이 출력

          //1 1 1 1 1

          //2 2 2 2 2

          //3 3 3 3 3

          //4 4 4 4 4

          //5 5 5 5 5

          int i=0, j=0;

          char text[20] = {0};

          for(i=1;i<=len;i++)

          {

                    for(j=1;j<=len;j++)

                    {

                               sprintf(text, "%d ", i);

                               WriteOutput(text);

                    }

                    WriteOutput("\n");

          }

}

 

void ProcType2(int len)

{

          //한변의 길이 len 정사각형을 아래와 같이 출력

          //1 2 3 4 5

          //5 4 3 2 1

          //1 2 3 4 5

          //5 4 3 2 1

          //1 2 3 4 5

          int i=0, j=0;

          int direction = 1;

          char text[20] = {0};

          for(i=1;i<=len;i++)

          {

                    if(direction)

                    {

                               for(j=1;j<=len;j++)

                               {

                                         sprintf(text, "%d ", j);

                                         WriteOutput(text);

                               }

                    }

                    else

                    {

                               for(j=len;j>0;j--)

                               {

                                         sprintf(text, "%d ", j);

                                         WriteOutput(text);

                               }

                    }

                   

                    direction = direction==1 ? 0 : 1;

 

                    WriteOutput("\n");

          }

}

void ProcType3(int len)

{

          //한변의 길이 len 정사각형을 아래와 같이 출력

          //1 2 3 4 5

          //2 4 6 8 10

          //3 6 9 12 15

          //4 8 12 16 20

          //5 10 1 20 25

          int i=0, j=0;

          int num = 0;

          char text[20] = {0};

 

          for(i=1;i<=len;i++)

          {

                    num = i;

                    for(j=1;j<=len;j++)

                    {

                               sprintf(text, "%d ", num);

                               WriteOutput(text);

                               num = num + i;

                    }

                    WriteOutput("\n");

          }

}

 

void RemoveOutput()

{

          unlink(OUT_FILE_NAME);

}

 

void WriteOutput(char *text)

{

          FILE* fs;

          char *res=0;

          fs=fopen(OUT_FILE_NAME,"a");

          if(fs)

          {

                    while(*text != '\0')

                    {

                               fwrite(text, 1, 1, fs);

                               text++;

                    }

                   

                    fclose(fs);

          }

}

void ReadInput(int *len, int *type)

{

          FILE* fs;

          char data[100]={0};

          char *res=0;

          fs=fopen(INPUT_FILE_NAME,"r");

          if(fs)

          {

                    fread(data, sizeof(char),5,fs);

                    *len = atoi(strtok(data, " "));

                    *type = atoi(strtok(0, " "));

                    fclose(fs);

          }

}

 

모든 문제는 C/C++, Java, Python 를 사용할수 있습니다.

기초다지기만 표준 입출력방식을 사용하고, 그외 모든 문제는 파일입출력으로 하셔야 채점이 가능합니다.

입력파일은 "input.txt", 출력파일은 "output.txt"입니다.

 

 

 

 

구현한 코드 :

 

#include <stdio.h> #include <stdlib.h> #include <string.h> #define OUT_FILE_NAME "output.txt" #define INPUT_FILE_NAME "input.txt" void ReadInput(int *row, int *col); void WriteOutput(char *text); void RemoveOutput(); void Proc(int row, int col); int main() { int row =0, col=0; RemoveOutput(); ReadInput(&row, &col); Proc(row, col); return 0; } void RemoveOutput() { unlink(OUT_FILE_NAME); } void Proc(int row, int col) { int direction=1; int i=0,j=0; int num = 1; char text[20] = {0}; for(i=0;i<row;i++) { for(j=0;j<col;j++) { if(direction) sprintf(text, "%d ", num++); else sprintf(text, "%d ", num--); WriteOutput(text); } if(direction) num--; else num++; direction = direction == 0? 1:0; WriteOutput("\n"); num += col; } } void WriteOutput(char *text) { FILE* fs; char *res=0; fs=fopen(OUT_FILE_NAME,"a"); if(fs) { while(*text != '\0') { fwrite(text, 1, 1, fs); text++; } fclose(fs); } } void ReadInput(int *row, int *col) { FILE* fs; char data[100]={0}; char *res=0; fs=fopen(INPUT_FILE_NAME,"r"); if(fs) { fread(data, sizeof(char),5,fs); *row = atoi(strtok(data, " ")); *col = atoi(strtok(0, " ")); fclose(fs); } } 

 

 

 

순대곱창볶음이 땡기던 날이였는데

영등포엔 순대곱창볶음을 잘하는 곳이 없어서

고민하던 순간

 

시식으로 사장님께서

순대곱창볶음을 주시더라구요

신나2

 

 

먹어보고 바로 여기로

GoGo!!

 

들어가려다 보인

open event!!ㅋㅋㅋㅋㅋ

 

참이슬 + 처음처럼 = 3000원

하트3

 

 

 

돈막골의 메뉴판이에요

 

저희는 곱창볶음 2인분과

소주를 주문했어요 ㅋㅋ

 

 

 

곱창볶음과 순대볶음이

따로 메뉴가 되있고 합쳐진 메뉴는 없길래

물어보니 섞어 달라면

섞어주시다는...

 

다음엔 섞어서 먹어야겠어요 ㅋㅋㅋㅋㅋ

 

밑반찬은 미나리무침, 정체모를 나물, 깻잎

청양고추, 마늘, 쌈장

그리고 오이냉국이 나와요 ㅋㅋ

 

 

 

남자친구는 오이냉국을 안먹으니

2그릇다 내꺼!ㅋㅋ

 

 

 

 

곱창볶음을 주문하면 2~3분 후에

이렇게 짜잔하고 나와요 ㅋㅋㅋ

맛있겠쭁??

 

아쉬운건 깻잎이 아주 쪼금~ 들어가요

그래서 꼭 깻잎에 싸먹었어요

 

 

부드럽고 씹히는 맛이!

최고!!!!ㅋㅋㅋㅋ

 

곱창볶음엔 쏘주 한잔

하트3

 

아까 위에서 말한 이벤트로

참이슬 + 처음처럼을 먹었어용

 

 

 

마지막엔 항상 볶음밥으로 마므으리~~~

 

 

 

비교적 괜찮았던 식당이에용

영등포에서 곱창볶음 먹으러는 여기로 가야겠네요 ㅋㅋ

 

 

 

 

 

 

 

 

 

 

+ Recent posts