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

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