source: trunk/Utilities/GenerateMathProblem01/GenerateMathProblem01.cpp @ 53

Last change on this file since 53 was 53, checked in by roman, 12 years ago
  • Property svn:keywords set to Id
File size: 5.4 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2012
3// Created by Roman Ryltsov roman@alax.info
4//
5// $Id: GenerateMathProblem01.cpp 53 2012-02-23 18:54:17Z roman $
6
7#include "stdafx.h"
8
9class Item
10{
11public:
12// Item
13        virtual INT GetPriority()
14        {
15                return 0;
16        }
17        virtual BOOL IsCommutative()
18        {
19                return TRUE;
20        }
21        virtual CString AsString() = 0;
22        virtual BOOL IsOperation()
23        {
24                return FALSE;
25        }
26};
27
28class ValueItem :
29        public Item
30{
31private:
32        INT m_nValue;
33
34public:
35// ValueItem
36        ValueItem(INT nValue = 0) :
37                m_nValue(nValue)
38        {
39        }
40        INT GetValue() const
41        {
42                return m_nValue;
43        }
44        CString AsString()
45        {
46                CString sString;
47                sString.Format(_T("%d"), m_nValue);
48                return sString;
49        }
50};
51
52class OperationItem :
53        public Item
54{
55public:
56        Item* m_pItem1;
57        CHAR m_nSymbol;
58        Item* m_pItem2;
59
60public:
61// OperationItem
62        OperationItem() :
63                m_pItem1(NULL),
64                m_pItem2(NULL)
65        {
66        }
67        INT GetPriority()
68        {
69                switch(m_nSymbol)
70                {
71                case '+':
72                case '-':
73                        return 2;
74                case '*':
75                case '/':
76                        return 1;
77                }
78                return 0;
79        }
80        BOOL IsCommutative()
81        {
82                switch(m_nSymbol)
83                {
84                case '-':
85                case '/':
86                        return FALSE;
87                }
88                return __super::IsCommutative();
89        }
90        CString AsString()
91        {
92                CString sString;
93                if(m_pItem1->GetPriority() > GetPriority())
94                        sString.AppendFormat(_T("(%s)"), m_pItem1->AsString());
95                else
96                        sString.Append(m_pItem1->AsString());
97                sString.AppendFormat(_T(" %c "), m_nSymbol);
98                if(m_pItem2->GetPriority() > GetPriority() || m_pItem2->IsOperation() && m_pItem2->GetPriority() == GetPriority() && !IsCommutative())
99                        sString.AppendFormat(_T("(%s)"), m_pItem2->AsString());
100                else
101                        sString.Append(m_pItem2->AsString());
102                return sString;
103        }
104        BOOL IsOperation()
105        {
106                return TRUE;
107        }
108};
109
110VOID Generate()
111{
112        const INT nResult = 5 + rand() % 95; // Result would be 5..99
113        Item* pItem = new ValueItem(nResult);
114        #if defined(_DEBUG)
115        for(INT nCount = 3; nCount > 0; )
116        #else
117        for(INT nCount = 7 + rand() % 7; nCount > 0; )
118        #endif // defined(_DEBUG)
119        {
120                Item** ppBrokenItem = &pItem;
121                while((*ppBrokenItem)->IsOperation())
122                {
123                        OperationItem* pBrokenOperationItem = static_cast<OperationItem*>(*ppBrokenItem);
124                        ppBrokenItem = &((rand() % 2) ? pBrokenOperationItem->m_pItem1 : pBrokenOperationItem->m_pItem2);
125                }
126                ValueItem* pBrokenValueItem = static_cast<ValueItem*>(*ppBrokenItem);
127                OperationItem* pNewOperationItem = new OperationItem;
128                static const INT g_nAddWeight = 15;
129                static const INT g_nSubtractWeight = 10;
130                static const INT g_nMultiplyWeight = 70;
131                static const INT g_nDivideWeight = 5;
132                INT nOperation = rand() % (g_nAddWeight + g_nSubtractWeight + g_nMultiplyWeight + g_nDivideWeight);
133                for(; ; )
134                {
135                        #pragma region Add
136                        nOperation -= g_nAddWeight;
137                        if(nOperation < 0)
138                        {
139                                const INT nAddend = 5 + rand() % 95; // Result would be 5..99
140                                if(pBrokenValueItem->GetValue() - nAddend < 0)
141                                {
142                                        pNewOperationItem = NULL;
143                                        break; // New Value Item is Negative
144                                }
145                                if(rand() % 2)
146                                {
147                                        pNewOperationItem->m_pItem1 = new ValueItem(pBrokenValueItem->GetValue() - nAddend);
148                                        pNewOperationItem->m_pItem2 = new ValueItem(nAddend);
149                                } else
150                                {
151                                        pNewOperationItem->m_pItem1 = new ValueItem(nAddend);
152                                        pNewOperationItem->m_pItem2 = new ValueItem(pBrokenValueItem->GetValue() - nAddend);
153                                }
154                                pNewOperationItem->m_nSymbol = '+';
155                                break;
156                        }
157                        #pragma endregion
158                        #pragma region Subtract
159                        nOperation -= g_nSubtractWeight;
160                        if(nOperation < 0)
161                        {
162                                const INT nSubtrahend = 5 + rand() % 95; // Result would be 5..99
163                                pNewOperationItem->m_pItem1 = new ValueItem(pBrokenValueItem->GetValue() + nSubtrahend);
164                                pNewOperationItem->m_nSymbol = '-';
165                                pNewOperationItem->m_pItem2 = new ValueItem(nSubtrahend);
166                                break;
167                        }
168                        #pragma endregion
169                        #pragma region Multiply
170                        nOperation -= g_nMultiplyWeight;
171                        if(nOperation < 0)
172                        {
173                                const INT nFactor = 5 + rand() % 95; // Result would be 5..99
174                                if(pBrokenValueItem->GetValue() % nFactor)
175                                {
176                                        pNewOperationItem = NULL;
177                                        break; // There is a Remainder
178                                }
179                                if(rand() % 2)
180                                {
181                                        pNewOperationItem->m_pItem1 = new ValueItem(pBrokenValueItem->GetValue() / nFactor);
182                                        pNewOperationItem->m_pItem2 = new ValueItem(nFactor);
183                                } else
184                                {
185                                        pNewOperationItem->m_pItem1 = new ValueItem(nFactor);
186                                        pNewOperationItem->m_pItem2 = new ValueItem(pBrokenValueItem->GetValue() / nFactor);
187                                }
188                                pNewOperationItem->m_nSymbol = '*';
189                                break;
190                        }
191                        #pragma endregion
192                        #pragma region Divide
193                        //nOperation -= g_nDivideWeight;
194                        //if(nOperation < 0)
195                        {
196                                const INT nDivisor = 5 + rand() % 95; // Result would be 5..99
197                                pNewOperationItem->m_pItem1 = new ValueItem(pBrokenValueItem->GetValue() * nDivisor);
198                                pNewOperationItem->m_nSymbol = ':';
199                                pNewOperationItem->m_pItem2 = new ValueItem(nDivisor);
200                                break;
201                        }
202                        #pragma endregion
203                }
204                if(!pNewOperationItem)
205                        continue;
206                *ppBrokenItem = pNewOperationItem;
207                nCount--;
208        }
209        _tprintf(_T("%s = %d\n"), pItem->AsString(), nResult);
210}
211
212int _tmain(int argc, _TCHAR* argv[])
213{
214        srand(1);
215        for(INT nCount = 0; nCount < 1000; nCount++)
216        {
217                #if defined(_DEBUG)
218                _tprintf(_T("%d: "), nCount);
219                #endif // defined(_DEBUG)
220                Generate();
221                if(nCount % 10 == 9)
222                        _tprintf(_T("\n"));
223        }
224        // NOTE: Who cares about memory leaks, right?
225        return 0;
226}
227
Note: See TracBrowser for help on using the repository browser.