Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
dispatcher_example.C
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
92#include <iostream>
93#include <iomanip>
94#include <string>
95#include <functional>
96#include <sstream>
97
98#include <ah-dispatcher.H>
99#include <tpl_dynArray.H>
100
101using namespace std;
102using namespace Aleph;
103
104// ============================================================================
105// Helper functions
106// ============================================================================
107
108void print_header(const string& title)
109{
110 cout << "\n";
111 cout << "+" << string(70, '-') << "+" << endl;
112 cout << "| " << left << setw(68) << title << " |" << endl;
113 cout << "+" << string(70, '-') << "+" << endl;
114}
115
116void print_subheader(const string& subtitle)
117{
118 cout << "\n " << subtitle << endl;
119 cout << " " << string(subtitle.length(), '-') << endl;
120}
121
122// ============================================================================
123// Example 1: Calculator with function pointers
124// ============================================================================
125
129namespace Calculator
130{
131 double add(double a, double b) { return a + b; }
132 double sub(double a, double b) { return a - b; }
133 double mul(double a, double b) { return a * b; }
134 double div(double a, double b)
135 {
136 if (b == 0) throw runtime_error("Division by zero");
137 return a / b;
138 }
139 double mod(double a, double b)
140 {
141 return static_cast<int>(a) % static_cast<int>(b);
142 }
143 double pow(double a, double b) { return std::pow(a, b); }
144}
145
147{
148 print_header("Example 1: Calculator with Function Pointers");
149
150 // Create dispatcher with character keys and function pointers
151 using CalcOp = double(*)(double, double);
153
154 // Register operations
161
162 cout << "\n Registered operations: + - * / % ^\n" << endl;
163
164 // Test cases
165 struct TestCase { double a; char op; double b; };
167 tests.append({10, '+', 5});
168 tests.append({10, '-', 3});
169 tests.append({7, '*', 8});
170 tests.append({100, '/', 4});
171 tests.append({17, '%', 5});
172 tests.append({2, '^', 10});
173
174 cout << " Expression Result" << endl;
175 cout << " " << string(35, '-') << endl;
176
177 for (size_t i = 0; i < tests.size(); ++i)
178 {
179 auto& t = tests(i);
180 if (calc.valid_key(t.op))
181 {
182 double result = calc.run(t.op, t.a, t.b);
183 cout << " " << setw(6) << t.a << " " << t.op << " "
184 << setw(6) << t.b << " = " << setw(10) << result << endl;
185 }
186 }
187
188 // Show that invalid keys are detected
189 cout << "\n Checking for unregistered operation '!':" << endl;
190 cout << " valid_key('!') = " << (calc.valid_key('!') ? "true" : "false") << endl;
191}
192
193// ============================================================================
194// Example 2: Text processor with lambdas
195// ============================================================================
196
198{
199 print_header("Example 2: Text Processor with Lambdas");
200
201 using TextOp = function<string(const string&)>;
203
204 // Register text transformations
205 processor.insert("upper", [](const string& s) {
206 string result = s;
207 for (char& c : result) c = toupper(c);
208 return result;
209 });
210
211 processor.insert("lower", [](const string& s) {
212 string result = s;
213 for (char& c : result) c = tolower(c);
214 return result;
215 });
216
217 processor.insert("reverse", [](const string& s) {
218 return string(s.rbegin(), s.rend());
219 });
220
221 processor.insert("length", [](const string& s) {
222 return to_string(s.length()) + " characters";
223 });
224
225 processor.insert("words", [](const string& s) {
226 int count = 0;
227 bool in_word = false;
228 for (char c : s) {
229 if (isspace(c)) in_word = false;
230 else if (!in_word) { count++; in_word = true; }
231 }
232 return to_string(count) + " words";
233 });
234
235 processor.insert("vowels", [](const string& s) {
236 int count = 0;
237 for (char c : s) {
238 char lower = tolower(c);
239 if (lower == 'a' || lower == 'e' || lower == 'i' ||
240 lower == 'o' || lower == 'u')
241 count++;
242 }
243 return to_string(count) + " vowels";
244 });
245
246 // Test text - Colombian theme
247 string text = "Colombia es un pais de gente trabajadora";
248
249 cout << "\n Original text: \"" << text << "\"\n" << endl;
250
251 cout << " Transformation Result" << endl;
252 cout << " " << string(55, '-') << endl;
253
255 operations.append("upper");
256 operations.append("lower");
257 operations.append("reverse");
258 operations.append("length");
259 operations.append("words");
260 operations.append("vowels");
261
262 for (size_t i = 0; i < operations.size(); ++i)
263 {
264 const string& op = operations(i);
265 string result = processor.run(op, text);
266 cout << " " << left << setw(18) << op << result << endl;
267 }
268
269 // Show available keys
270 cout << "\n Available operations: ";
271 auto keys = processor.keys();
272 for (auto it = keys.get_it(); it.has_curr(); it.next_ne())
273 cout << it.get_curr() << " ";
274 cout << endl;
275}
276
277// ============================================================================
278// Example 3: Colombian Regions Information System
279// ============================================================================
280
282{
283 print_header("Example 3: Colombian Regions Information System");
284
285 using RegionInfo = function<void()>;
287
288 regions.insert("andina", []() {
289 cout << "\n REGION ANDINA" << endl;
290 cout << " Capital: Bogota" << endl;
291 cout << " Departments: Cundinamarca, Boyaca, Santander, Antioquia..." << endl;
292 cout << " Climate: Temperate to cold (varies with altitude)" << endl;
293 cout << " Products: Coffee, flowers, potatoes, emeralds" << endl;
294 });
295
296 regions.insert("caribe", []() {
297 cout << "\n REGION CARIBE" << endl;
298 cout << " Major cities: Barranquilla, Cartagena, Santa Marta" << endl;
299 cout << " Departments: Atlantico, Bolivar, Magdalena, La Guajira..." << endl;
300 cout << " Climate: Tropical hot" << endl;
301 cout << " Products: Bananas, coal, tourism, fishing" << endl;
302 });
303
304 regions.insert("pacifica", []() {
305 cout << "\n REGION PACIFICA" << endl;
306 cout << " Major cities: Cali, Buenaventura, Quibdo" << endl;
307 cout << " Departments: Valle del Cauca, Choco, Narino, Cauca" << endl;
308 cout << " Climate: Very humid tropical" << endl;
309 cout << " Products: Sugar cane, timber, gold, platinum" << endl;
310 });
311
312 regions.insert("orinoquia", []() {
313 cout << "\n REGION ORINOQUIA (Los Llanos)" << endl;
314 cout << " Major cities: Villavicencio, Yopal" << endl;
315 cout << " Departments: Meta, Casanare, Arauca, Vichada" << endl;
316 cout << " Climate: Tropical with dry season" << endl;
317 cout << " Products: Cattle, oil, rice, palm oil" << endl;
318 });
319
320 regions.insert("amazonia", []() {
321 cout << "\n REGION AMAZONIA" << endl;
322 cout << " Major cities: Leticia, Florencia" << endl;
323 cout << " Departments: Amazonas, Caqueta, Putumayo, Guaviare" << endl;
324 cout << " Climate: Humid equatorial" << endl;
325 cout << " Products: Timber, rubber, ecotourism, biodiversity" << endl;
326 });
327
328 regions.insert("insular", []() {
329 cout << "\n REGION INSULAR" << endl;
330 cout << " Islands: San Andres, Providencia, Santa Catalina" << endl;
331 cout << " Location: Caribbean Sea" << endl;
332 cout << " Climate: Tropical maritime" << endl;
333 cout << " Products: Tourism, coconut, fishing" << endl;
334 });
335
336 // Display all regions
338 region_codes.append("andina");
339 region_codes.append("caribe");
340 region_codes.append("pacifica");
341 region_codes.append("orinoquia");
342 region_codes.append("amazonia");
343 region_codes.append("insular");
344
345 cout << "\n Colombia's Natural Regions:" << endl;
346 cout << " " << string(40, '=') << endl;
347
348 for (size_t i = 0; i < region_codes.size(); ++i)
349 regions.run(region_codes(i));
350}
351
352// ============================================================================
353// Example 4: Order State Machine
354// ============================================================================
355
357{
358 print_header("Example 4: Order Processing State Machine");
359
360 // Order state
361 struct Order {
362 int id;
363 string state;
364 string customer;
365 double amount;
366 string history;
367
368 void log(const string& action) {
369 history += " -> " + action + " (from " + state + ")\n";
370 }
371 };
372
373 Order order = {1001, "created", "Juan Perez", 250000.0, ""};
374
375 using StateAction = function<void(Order&)>;
377
378 // Define state transitions
379 state_machine.insert("confirm", [](Order& o) {
380 if (o.state != "created") {
381 cout << " [ERROR] Cannot confirm - order not in 'created' state" << endl;
382 return;
383 }
384 o.log("confirmed");
385 o.state = "confirmed";
386 cout << " [OK] Order " << o.id << " confirmed" << endl;
387 });
388
389 state_machine.insert("pay", [](Order& o) {
390 if (o.state != "confirmed") {
391 cout << " [ERROR] Cannot pay - order not confirmed" << endl;
392 return;
393 }
394 o.log("paid");
395 o.state = "paid";
396 cout << " [OK] Payment of $" << fixed << setprecision(0) << o.amount
397 << " COP received" << endl;
398 });
399
400 state_machine.insert("ship", [](Order& o) {
401 if (o.state != "paid") {
402 cout << " [ERROR] Cannot ship - order not paid" << endl;
403 return;
404 }
405 o.log("shipped");
406 o.state = "shipped";
407 cout << " [OK] Order shipped to " << o.customer << endl;
408 });
409
410 state_machine.insert("deliver", [](Order& o) {
411 if (o.state != "shipped") {
412 cout << " [ERROR] Cannot deliver - order not shipped" << endl;
413 return;
414 }
415 o.log("delivered");
416 o.state = "delivered";
417 cout << " [OK] Order delivered successfully!" << endl;
418 });
419
420 state_machine.insert("cancel", [](Order& o) {
421 if (o.state == "delivered") {
422 cout << " [ERROR] Cannot cancel delivered order" << endl;
423 return;
424 }
425 o.log("cancelled");
426 o.state = "cancelled";
427 cout << " [OK] Order cancelled" << endl;
428 });
429
430 // Process the order through its lifecycle
431 cout << "\n Order #" << order.id << " - Customer: " << order.customer << endl;
432 cout << " Amount: $" << fixed << setprecision(0) << order.amount << " COP" << endl;
433 cout << "\n Processing order:" << endl;
434 cout << " " << string(40, '-') << endl;
435
436 // Normal flow
437 state_machine.run("confirm", order);
438 state_machine.run("pay", order);
439 state_machine.run("ship", order);
440 state_machine.run("deliver", order);
441
442 // Try invalid transition
443 cout << "\n Attempting invalid transition:" << endl;
444 state_machine.run("cancel", order); // Should fail
445
446 // Show history
447 cout << "\n Order History:" << endl;
448 cout << order.history;
449 cout << " Final state: " << order.state << endl;
450}
451
452// ============================================================================
453// Example 5: High-performance Hash Dispatcher
454// ============================================================================
455
457{
458 print_header("Example 5: Hash-based Dispatcher Performance");
459
460 // For very frequent lookups, AhHashDispatcher provides O(1) access
461 using MetricHandler = function<double(double)>;
463
464 // Colombian economic indicators transformations
465 metrics.insert("usd_to_cop", [](double usd) {
466 return usd * 4150.0; // Approximate rate
467 });
468
469 metrics.insert("cop_to_usd", [](double cop) {
470 return cop / 4150.0;
471 });
472
473 metrics.insert("inflation_adjust", [](double value) {
474 return value * 1.12; // 12% annual inflation adjustment
475 });
476
477 metrics.insert("vat", [](double price) {
478 return price * 1.19; // 19% VAT
479 });
480
481 metrics.insert("income_tax", [](double income) {
482 // Simplified Colombian income tax
483 if (income < 4500000) return 0.0;
484 if (income < 10000000) return (income - 4500000) * 0.19;
485 if (income < 25000000) return (income - 10000000) * 0.28 + 1045000;
486 return (income - 25000000) * 0.33 + 5245000;
487 });
488
489 cout << "\n Colombian Economic Calculations:" << endl;
490 cout << " " << string(50, '-') << endl;
491
492 // Currency conversions
493 double usd_amount = 100.0;
494 cout << "\n Currency Conversion:" << endl;
495 cout << " $" << usd_amount << " USD = $" << fixed << setprecision(0)
496 << metrics.run("usd_to_cop", usd_amount) << " COP" << endl;
497
498 double cop_amount = 1000000.0;
499 cout << " $" << cop_amount << " COP = $" << setprecision(2)
500 << metrics.run("cop_to_usd", cop_amount) << " USD" << endl;
501
502 // Price calculations
503 cout << "\n Price Calculations:" << endl;
504 double base_price = 500000.0;
505 cout << " Base price: $" << setprecision(0) << base_price << " COP" << endl;
506 cout << " With VAT (19%): $" << metrics.run("vat", base_price) << " COP" << endl;
507 cout << " Inflation adjusted: $" << metrics.run("inflation_adjust", base_price)
508 << " COP" << endl;
509
510 // Income tax examples
511 cout << "\n Monthly Income Tax Examples:" << endl;
513 incomes.append(3000000);
514 incomes.append(6000000);
515 incomes.append(15000000);
516 incomes.append(30000000);
517
518 for (size_t i = 0; i < incomes.size(); ++i)
519 {
520 double income = incomes(i);
521 double tax = metrics.run("income_tax", income);
522 cout << " Income $" << setw(12) << income << " COP -> Tax: $"
523 << setw(10) << tax << " COP" << endl;
524 }
525}
526
527// ============================================================================
528// Example 6: Dispatcher with Variadic Arguments
529// ============================================================================
530
532{
533 print_header("Example 6: Variadic Arguments Dispatcher");
534
535 // Dispatcher that handles different argument counts
536 using FlexOp = function<string(const DynArray<string>&)>;
538
539 flex.insert("join", [](const DynArray<string>& args) {
540 string result;
541 for (size_t i = 0; i < args.size(); ++i) {
542 if (i > 0) result += " ";
543 result += args(i);
544 }
545 return result;
546 });
547
548 flex.insert("concat", [](const DynArray<string>& args) {
549 string result;
550 for (size_t i = 0; i < args.size(); ++i)
551 result += args(i);
552 return result;
553 });
554
555 flex.insert("first", [](const DynArray<string>& args) {
556 return args.size() > 0 ? args(0) : "";
557 });
558
559 flex.insert("last", [](const DynArray<string>& args) {
560 return args.size() > 0 ? args(args.size() - 1) : "";
561 });
562
563 flex.insert("count", [](const DynArray<string>& args) {
564 return to_string(args.size()) + " arguments";
565 });
566
567 // Test with Colombian city names
569 cities.append("Bogota");
570 cities.append("Medellin");
571 cities.append("Cali");
572 cities.append("Barranquilla");
573 cities.append("Cartagena");
574
575 cout << "\n Arguments: Bogota, Medellin, Cali, Barranquilla, Cartagena\n" << endl;
576
577 cout << " Operation Result" << endl;
578 cout << " " << string(50, '-') << endl;
579
580 cout << " join: " << flex.run("join", cities) << endl;
581 cout << " concat: " << flex.run("concat", cities) << endl;
582 cout << " first: " << flex.run("first", cities) << endl;
583 cout << " last: " << flex.run("last", cities) << endl;
584 cout << " count: " << flex.run("count", cities) << endl;
585}
586
587// ============================================================================
588// Main
589// ============================================================================
590
591int main()
592{
593 cout << "\n";
594 cout << "========================================================================" << endl;
595 cout << " ALEPH-W DISPATCHER EXAMPLE" << endl;
596 cout << " Dynamic Command Dispatching" << endl;
597 cout << "========================================================================" << endl;
598
605
606 cout << "\n";
607 cout << "========================================================================" << endl;
608 cout << " Example completed successfully!" << endl;
609 cout << "========================================================================" << endl;
610 cout << endl;
611
612 return 0;
613}
614
Command dispatcher pattern implementation.
Tree-based command dispatcher.
Hash-based command dispatcher.
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
size_t length() const noexcept
Count the number of elements of a container.
Definition ah-dry.H:1385
void demo_state_machine()
void demo_hash_dispatcher()
void demo_calculator()
void demo_variadic_dispatcher()
void demo_regions_menu()
void demo_text_processor()
void print_subheader(const string &subtitle)
int main()
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_log_function > > log(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4063
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
std::string tolower(const char *str)
Convert a C std::string to lower-case.
std::string to_string(const time_t t, const std::string &format)
Format a time_t value into a string using format.
Definition ah-date.H:140
std::string toupper(const char *str)
Convert a C std::string to upper-case.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
Basic arithmetic operations for the calculator.
double sub(double a, double b)
double add(double a, double b)
double div(double a, double b)
double mul(double a, double b)
double pow(double a, double b)
double mod(double a, double b)
STL namespace.
void print_header()
Aleph::DynList< T > keys() const
Definition ah-dry.H:1516
Lazy and scalable dynamic array implementation.