Compare commits

...

34 Commits

Author SHA1 Message Date
Jidong Xiao
04af78b253 7, not 9 2025-03-12 10:04:04 -04:00
Jidong Xiao
dc7c973256 removing the redundant $ sign 2025-03-12 10:04:04 -04:00
Jidong Xiao
c9bd945e27 renaming 2025-03-12 10:04:04 -04:00
Jidong Xiao
aaecda717c renaming 2025-03-12 10:04:04 -04:00
Jidong Xiao
3f47154335 renaming 2025-03-12 10:04:04 -04:00
Jidong Xiao
94e66529f4 renaming 2025-03-12 10:04:04 -04:00
Jidong Xiao
af2c2bddd2 adding the move constructor example for map insert 2025-03-12 10:04:04 -04:00
Jidong Xiao
cf9b51d64a fixing syntax issue 2025-03-12 10:04:04 -04:00
Jidong Xiao
c34d107f78 adding link to the benchmark document 2025-03-12 10:04:04 -04:00
Jidong Xiao
bb7486a01b adding link to the benchmark document 2025-03-12 10:04:04 -04:00
Jidong Xiao
890d4d2be8 renaming 2025-03-12 10:04:04 -04:00
Jidong Xiao
95d9bb50ca adding benchmarks and readme 2025-03-12 10:04:04 -04:00
Jidong Xiao
186a7e60ea adding author information 2025-03-12 10:04:04 -04:00
Jidong Xiao
a7239d00a9 case 5 not 4 2025-03-12 10:04:04 -04:00
Jidong Xiao
d2d1a34eec case 5 not 4 2025-03-12 10:04:04 -04:00
Jidong Xiao
23ac44932a fixing the konva path 2025-03-12 10:04:04 -04:00
Jidong Xiao
4a88689106 adding the stack animation 2025-03-12 10:04:04 -04:00
Jidong Xiao
c26e4f8fc3 adding the animation 2025-03-12 10:04:04 -04:00
Jidong Xiao
3d5614564f doesn't have to be nested 2025-03-12 10:04:04 -04:00
Jidong Xiao
07f53dedfe 40 max submissions 2025-03-12 10:04:04 -04:00
Jidong Xiao
67c5cb8641 adding faqs 2025-03-12 10:04:04 -04:00
Jidong Xiao
28d01974f1 adding faqs 2025-03-12 10:04:04 -04:00
Jidong Xiao
281c47d771 adding the FAQs 2025-03-12 10:04:04 -04:00
Jidong Xiao
df38b3cf36 adding the FAQs 2025-03-12 10:04:04 -04:00
Jidong Xiao
79e526004b adding other test cases used by submitty 2025-03-12 10:04:04 -04:00
Jidong Xiao
0be3f92396 adding the cpp file 2025-03-12 10:04:04 -04:00
Jidong Xiao
d8f573c722 add the main function 2025-03-12 10:04:04 -04:00
Jidong Xiao
6929005253 remove redundant lines 2025-03-12 10:04:03 -04:00
Jidong Xiao
086aad56cf move pairs up 2025-03-12 10:04:03 -04:00
Jidong Xiao
23acdc2bea notes about struct 2025-03-12 10:04:03 -04:00
Jidong Xiao
a37e7408b7 renaming 2025-03-12 10:04:03 -04:00
Jidong Xiao
4df57b18b3 no analysis 2025-03-12 10:04:03 -04:00
Jidong Xiao
d7dd0f1e80 adding input and output files 2025-03-12 10:04:03 -04:00
Jidong Xiao
da64e34f47 updating readme 2025-03-12 10:04:03 -04:00
41 changed files with 1301 additions and 101 deletions

View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Valid Parentheses</title>
<script src="../konva.js"></script>
</head>
<body>
<h1>Valid Parentheses</h1>
<p>This animation shows if parentheses entered are valid using stack</p>
<button onclick="case1()">Case 1: "()"</button>
<button onclick="case2()">Case 2: "()[]{}"</button>
<button onclick="case3()">Case 3: "(]"</button>
<button onclick="case4()">Case 4: "([])"</button>
<button onclick="case5()">Case 5: "{[([])]}"</button>
<div id="container"></div>
<script src="stack.js"></script>
</body>
</html>

605
animations/stack/stack.js Normal file
View File

@@ -0,0 +1,605 @@
// Author: Mykolas Ruth
// Create a stage for the animation
var stage = new Konva.Stage({
container: 'container',
width: 1200,
height: 700
});
// Create layer
var layer = new Konva.Layer();
// Variables to track animation state
var stack = [];
var lastPopped = "";
var currentString = "";
var currentIndex = 0;
var pc = 0; // Program counter for animation steps
var isComplete = false;
// Stack size and positioning
var stack_size = 10;
var stack_x = 1000;
var stack_y = 100;
var stack_width = 120;
var stack_height = 40;
// Initialize the visualization
function init() {
// Reset layer
layer.destroyChildren();
// Create code display
createCodeDisplay();
// Create stack visualization
createStack();
// Create animation controls area
createNextStepButton();
// Add the layer to the stage
stage.add(layer);
layer.draw();
}
// Create the code display
function createCodeDisplay() {
var codeRect = new Konva.Rect({
x: 50,
y: 50,
width: 450,
height: 600,
stroke: '#555',
strokeWidth: 2,
fill: '#f5f5f5',
shadowColor: 'black',
shadowBlur: 10,
shadowOffsetX: 5,
shadowOffsetY: 5,
shadowOpacity: 0.2,
cornerRadius: 10,
id: 'code_rect'
});
layer.add(codeRect);
// Add the code text
var codeLines = [
"bool isValid(string s) {",
" std::stack<char> myStack;",
" int len = s.length();",
" char c;",
" for(int i=0; i<len; i++) {",
" // Push opening brackets to stack",
" if(s[i]=='(' || s[i]=='{' || s[i]=='[') {",
" myStack.push(s[i]);",
" } else {",
" // Check for closing brackets",
" if(myStack.empty()) {",
" return false;",
" }",
" c = myStack.top();",
" myStack.pop();",
" // Check bracket matching",
" if(s[i]==')' && c!='(') return false;",
" if(s[i]=='}' && c!='{') return false;",
" if(s[i]==']' && c!='[') return false;",
" }",
" }",
" // Check if all brackets are matched",
" return myStack.empty();",
"}"
];
for (var i = 0; i < codeLines.length; i++) {
makeText(60, 60 + i * 20, codeLines[i], 'code_line_' + i);
}
}
// Create the stack boxes
function createStack() {
makeText(stack_x, stack_y - 50, "Stack", "stack_title");
// rectangles on stack
for (var i = 0; i < stack_size; i++) {
var rect = new Konva.Rect({
x: stack_x,
y: stack_y + i * stack_height,
id: "stack_rec" + i,
stroke: '#343434',
strokeWidth: 2,
fill: '#f0f0f0',
width: stack_width,
height: stack_height,
});
layer.add(rect);
}
var base = new Konva.Rect({
x: stack_x,
y: stack_y + stack_size * stack_height,
width: stack_width,
height: 5,
fill: 'black',
});
layer.add(base);
}
// create next step button
function createNextStepButton() {
var nextStepButton = new Konva.Label({
x: 530,
y: 400,
});
nextStepButton.add(new Konva.Tag({
fill: 'blue',
cornerRadius: 3,
shadowColor: 'black',
}));
nextStepButton.add(new Konva.Text({
text: 'Next Step',
fontSize: 18,
padding: 10,
fill: 'white'
}));
nextStepButton.on('click', function() {
nextStep();
});
layer.add(nextStepButton);
}
// Create the input string display
function createInputDisplay(str) {
// Clear previous displays
var prevDisplay = stage.find('#input_display');
prevDisplay.each(function(node) {
node.destroy();
});
// Input string display title
makeText(520, 50, "Input: string s = \"" + str + "\"", "input_title");
// Create boxes for each character
var boxWidth = 40;
var boxSpacing = 10;
var startX = 520;
var startY = 100;
var group = new Konva.Group({
id: 'input_display'
});
for (var i = 0; i < str.length; i++) {
var charBox = new Konva.Rect({
x: startX + i * (boxWidth + boxSpacing),
y: startY,
width: boxWidth,
height: boxWidth,
fill: '#f0f0f0',
stroke: '#555',
strokeWidth: 1,
cornerRadius: 4,
id: 'char_box_' + i
});
var charText = new Konva.Text({
x: startX + i * (boxWidth + boxSpacing) + 12,
y: startY + 10,
text: str[i],
fontSize: 20,
fontFamily: 'monospace',
fill: 'black',
id: 'char_text_' + i
});
group.add(charBox);
group.add(charText);
}
// Create the character pointer (initially at first character)
var pointer = new Konva.RegularPolygon({
x: startX + boxWidth/2,
y: startY - 15,
sides: 3,
radius: 12,
fill: 'red',
rotation: 180,
id: 'char_pointer'
});
group.add(pointer);
layer.add(group);
}
// Create the result and explanations
function createResultDisplay() {
var prevDisplay = stage.find('#result_display');
prevDisplay.each(function(node) {
node.destroy();
});
var group = new Konva.Group({
id: 'result_display'
});
// Result display
var resultBox = new Konva.Rect({
x: 520,
y: 150,
width: 250,
height: 40,
fill: '#e0e0e0',
stroke: '#555',
strokeWidth: 1,
cornerRadius: 5,
id: 'result_box'
});
var resultText = new Konva.Text({
x: 530,
y: 160,
text: 'Output: Code Not Finished',
fontSize: 16,
fontFamily: 'Arial',
fill: 'black',
id: 'result_text'
});
// Explanation box
var explanationBox = new Konva.Rect({
x: 520,
y: 200,
width: 250,
height: 150,
fill: '#f0f0f0',
stroke: '#555',
strokeWidth: 1,
cornerRadius: 5,
id: 'explanation_box'
});
var explanationText = new Konva.Text({
x: 530,
y: 210,
text: 'Click "Next Step" to begin checking the brackets.',
fontSize: 16,
fontFamily: 'Arial',
fill: 'black',
width: 240,
id: 'explanation_text'
});
group.add(resultBox);
group.add(resultText);
group.add(explanationBox);
group.add(explanationText);
layer.add(group);
}
// Utility function to create text
function makeText(x, y, str, id, color) {
var text = new Konva.Text({
x: x,
y: y,
text: str,
id: 'text_' + id,
fontSize: 16,
fontFamily: 'Arial',
fill: color || 'black',
width: 1000,
});
layer.add(text);
return text;
}
// highlight current line in code
function highlightCodeLine(lineNum) {
for (var i = 0; i < 25; i++) {
var line = stage.find('#text_code_line_' + i);
if (line.length > 0) {
line[0].fontStyle('normal');
line[0].fill('black');
}
}
// highlight current line
var currentLine = stage.find('#text_code_line_' + lineNum);
if (currentLine.length > 0) {
currentLine[0].fontStyle('bold');
currentLine[0].fill('blue');
}
layer.draw();
}
// Move the character pointer
function movePointer(index) {
if (index < 0 || index >= currentString.length) return;
var charBox = stage.find('#char_box_' + index)[0];
var pointer = stage.find('#char_pointer')[0];
if (charBox && pointer) {
pointer.x(charBox.x() + charBox.width()/2);
}
layer.draw();
}
// Reset character highlight
function resetCharHighlight(index) {
if (index < 0 || index >= currentString.length) return;
var charBox = stage.find('#char_box_' + index)[0];
if (charBox) {
charBox.fill('#f0f0f0');
}
layer.draw();
}
// Push a character onto the stack
function pushToStack(char) {
stack.push(char);
var stackIndex = stack_size - stack.length;
// Add the character to the stack visual
var charText = new Konva.Text({
x: stack_x + stack_width/2 - 10,
y: stack_y + stackIndex * stack_height + 10,
text: char,
fontSize: 24,
fontFamily: 'monospace',
fill: 'black',
id: 'stack_item_' + stackIndex
});
layer.add(charText);
layer.draw();
}
// Pop a character from the stack
function popFromStack() {
if (stack.length === 0) return null;
var poppedChar = stack.pop();
var stackIndex = stack_size - stack.length - 1;
// Remove the character from the stack visual
stage.find('#stack_item_' + stackIndex).destroy();
// Reset the stack slot color
stage.find('#stack_rec' + stackIndex)[0].fill('#f0f0f0');
layer.draw();
return poppedChar;
}
// Update the result text
function updateResult(text, color) {
var resultText = stage.find('#result_text')[0];
if (resultText) {
resultText.text('Output: ' + text);
resultText.fill(color || 'black');
}
layer.draw();
}
// Update the explanation text
function updateExplanation(text) {
var explanationText = stage.find('#explanation_text')[0];
if (explanationText) {
explanationText.text(text);
}
layer.draw();
}
// Reset the animation state for a new case
function resetAnimation(str) {
// Reset state variables
currentString = str;
currentIndex = 0;
stack = [];
pc = 1;
isComplete = false;
// Reset visual elements
init();
createInputDisplay(str);
createResultDisplay();
// Reset all stack slots
for (var i = 0; i < stack_size; i++) {
stage.find('#stack_rec' + i)[0].fill('#f0f0f0');
}
// Initialize first step
highlightCodeLine(0);
updateResult('Code Not Finished', 'black');
updateExplanation('Click "Next Step" to begin checking the brackets: ' + str);
layer.draw();
}
// Process the next step of the animation
function nextStep() {
if (isComplete) return;
switch (pc) {
case 1:
// Initialize stack
highlightCodeLine(1);
updateExplanation("Creating an empty stack to store opening brackets");
pc++;
break;
case 2:
// Get length
highlightCodeLine(2);
updateExplanation("Getting the length of the string of brackets: " + currentString.length);
pc++;
break;
case 3:
// Initialize for loop
highlightCodeLine(4);
updateExplanation("Starting the loop to process each character");
pc++;
break;
case 4:
// Check if done with all characters
if (currentIndex >= currentString.length) {
// Final check if stack is empty
highlightCodeLine(21);
updateExplanation("All characters processed. Checking if the stack is empty...");
if (stack.length === 0) {
updateResult("True");
updateExplanation("The stack is empty, which means all opening brackets were matched with their closing brackets in the correct order. The string is valid.");
} else {
updateResult("False", "red");
updateExplanation("The stack still has " + stack.length + " unmatched opening bracket(s). This means some opening brackets were never matched with closing brackets. The string is invalid.");
}
isComplete = true;
break;
}
// Process current character
movePointer(currentIndex);
var currentChar = currentString[currentIndex];
updateExplanation("Processing character at index " + currentIndex + ": '" + currentChar + "'");
// Check if opening bracket
if (currentChar === '(' || currentChar === '{' || currentChar === '[') {
highlightCodeLine(6);
pc = 5; // Go to opening bracket logic
} else {
highlightCodeLine(8);
pc = 6; // Go to closing bracket logic
}
break;
case 5:
// Process opening bracket
var currentChar = currentString[currentIndex];
highlightCodeLine(7);
updateExplanation("Found opening bracket '" + currentChar + "'. Pushing it onto the stack to remember it.");
pushToStack(currentChar);
// Move to next character
resetCharHighlight(currentIndex);
currentIndex++;
pc = 4; // Return to character processing
break;
case 6:
// Process closing bracket - check if stack is empty
var currentChar = currentString[currentIndex];
highlightCodeLine(10);
if (stack.length === 0) {
updateExplanation("Found closing bracket '" + currentChar + "' but the stack is empty. This means there's no matching opening bracket, so the string is invalid.");
updateResult("false", "red");
isComplete = true;
break;
}
updateExplanation("Found closing bracket '" + currentChar + "'. Checking the top of the stack for a matching opening bracket.");
pc++;
break;
case 7:
// Get top of stack
var currentChar = currentString[currentIndex];
var topChar = stack[stack.length - 1];
highlightCodeLine(12);
updateExplanation("The top of the stack contains: '" + topChar + "'");
pc++;
break;
case 8:
// Pop from stack
var currentChar = currentString[currentIndex];
var topChar = stack[stack.length - 1];
highlightCodeLine(13);
updateExplanation("Popping '" + topChar + "' from the stack to compare with '" + currentChar + "'");
lastPopped = popFromStack();
pc++;
break;
case 9:
// Check if brackets match
var currentChar = currentString[currentIndex];
var topChar = lastPopped;
if (currentChar === ')') {
highlightCodeLine(15);
} else if (currentChar === '}') {
highlightCodeLine(16);
} else if (currentChar === ']') {
highlightCodeLine(17);
}
// Check if match failed
if ((currentChar === ')' && topChar !== '(') ||
(currentChar === '}' && topChar !== '{') ||
(currentChar === ']' && topChar !== '[')) {
updateExplanation("Mismatch! Closing bracket '" + currentChar + "' doesn't match with the opening bracket '" + topChar + "'. The string is invalid.");
updateResult("False");
isComplete = true;
break;
}
// Match succeeded
updateExplanation("Match found! Closing bracket '" + currentChar + "' correctly matches with opening bracket '" + topChar + "'." );
// Move to next character
resetCharHighlight(currentIndex);
currentIndex++;
pc = 4; // Return to character processing
break;
}
layer.draw();
}
// Case 1: "()"
function case1() {
resetAnimation("()");
}
// Case 2: "()[]{}"
function case2() {
resetAnimation("()[]{}");
}
// Case 3: "(]"
function case3() {
resetAnimation("(]");
}
// Case 4: "([])"
function case4() {
resetAnimation("([])");
}
// Case 5: "({[{[()]}]})"
function case5() {
resetAnimation("{[([])]}");
}
// Initialize the animation
init();
case1(); // Start with Case 1 by default

View File

@@ -1,11 +1,10 @@
**Special Note 1: A correct program does not necessarily pass all the test cases for this assignment, as Submitty may let you fail a test case if your program is not fast enough or consumes too much memory.**
**Special Note 2: For this assignment, we will not deduct points if you use data structures which have not been learned in this class. However, students who passed all test cases last semester did not use any of such data structures. In other words, using only data structures we have learned so far, is sufficient to pass all test cases.**
# Homework 6 — Inverse Word Search Recursion
In this homework we will build an inverse word search program using the techniques of recursion.
The goal is to construct a grid of letters that one can search to find specific words. Understanding the non-linear word
search program from Lectures 12 will be helpful in thinking about how you will solve this problem.
search program from Lectures 12/13 will be helpful in thinking about how you will solve this problem.
We strongly urge you to study and play with that program, including tracing through its behavior using a
debugger or cout statements or both. Please read the entire handout before beginning your implementation.
@@ -50,38 +49,56 @@ solution, your program should just output the first legal solution it finds (it
number of solutions, nor does it need to be the first solution shown in our output). If the puzzle is impossible
your program should output “No solutions found”.
**To implement this assignment, you must use recursion in your search.** First you should tackle the problem
of finding and outputting one legal solution to the puzzle (if one exists).
**To implement this assignment, you must use recursion in your search.** First you should tackle the problem of finding and outputting one legal solution to the puzzle (if one exists).
## Algorithm Analysis
<!-- ## Algorithm Analysis
For larger, more complex examples, this is a really hard problem. Your program should be able to handle
the small puzzles we have created in a reasonable amount of time. <!--You should make up your own test cases
as well to understand this complexity. Include these test cases with your submission (they will be graded).
Summarize the results of your testing, which test cases completed successfully and the approximate “wall
clock time” for completion of each test.--> The UNIX/WSL time command can be prepended to your command
line to estimate the running time:
For larger, more complex examples, this is a really hard problem. Your program should be able to handle the small puzzles we have created in a reasonable amount of time. You should make up your own test cases as well to understand this complexity. Include these test cases with your submission (they will be graded).
Summarize the results of your testing, which test cases completed successfully and the approximate “wall clock time” for completion of each test. The UNIX/WSL time command can be prepended to your command line to estimate the running time:
```console
time inverse_word_search.exe puzzle1.txt out1.txt one_solution
```
Once you have finished your implementation and testing, analyze the performance of your algorithm using
order notation. What important variables control the complexity of a particular problem? The width &
height of the grid (w and h), the number of required words (r), the number of forbidden words (f), the
number of letters in each word (l), the number of solutions (s)? In your plain text README.txt file, write
a concise paragraph (< 200 words) justifying your answer. <!--Also include a simple table summarizing the
running time and number of solutions found by your program on each of the provided examples. Note: Its
ok if your program cant solve the biggest puzzles in a reasonable amount of time.-->
Once you have finished your implementation and testing, analyze the performance of your algorithm using order notation. What important variables control the complexity of a particular problem? The width & height of the grid (w and h), the number of required words (r), the number of forbidden words (f), the number of letters in each word (l), the number of solutions (s)? In your plain text README.txt file, write a concise paragraph (< 200 words) justifying your answer. Also include a simple table summarizing the running time and number of solutions found by your program on each of the provided examples. Note: Its ok if your program cant solve the biggest puzzles in a reasonable amount of time.-->
## Program Requirements & Submission Details
Use good coding style when you design and implement your program. Organize your program into functions:
dont put all the code in main! Be sure to read the [Homework Policies](https://www.cs.rpi.edu/academics/courses/spring24/csci1200/homework_policies.php) as you put the finishing touches on your solution. Be sure to make up new test cases to fully debug your program and dont forget
dont put all the code in main! Be sure to read the [Homework Policies](https://www.cs.rpi.edu/academics/courses/spring25/csci1200/homework_policies.php) as you put the finishing touches on your solution. Be sure to make up new test cases to fully debug your program and dont forget
to comment your code! Use the provided template [README.txt](./README.txt) file for notes you want the grader to read.
You must do this assignment on your own, as described in the [Collaboration Policy & Academic Integrity](https://www.cs.rpi.edu/academics/courses/spring24/csci1200/academic_integrity.php) page. If you did discuss the problem or error messages, etc. with anyone, please list their names in your README.txt file.
You must do this assignment on your own, as described in the [Collaboration Policy & Academic Integrity](https://www.cs.rpi.edu/academics/courses/spring25/csci1200/academic_integrity.php) page. If you did discuss the problem or error messages, etc. with anyone, please list their names in your README.txt file.
**Due Date**: 03/14/2024, Thursday, 10pm.
**Due Date**: 03/13/2025, Thursday, 10pm.
## FAQs
1. Q: Am I allowed to use data structures not covered in this class?
A: Yes. For this homework, you can use whatever data structures you want to use; but last year, the student who topped the leaderboard with a very large margin, did not use any fancy data structures. The student used std::set, but did not use std::unordered_set or std::unordered_map, or any data structures which had not been covered in this class.
2. Q: Can I use global variables for this homework?
A: Yes, you can.
3. Q: Do I have to implement a class or classes?
A: It's not a requirement. You can if you want to.
4. Q: Which optimization flag does the Submitty compiler use?
A: Submitty uses -O3 for this homework.
5. Q: How many submissions can I make?
A: 40. Submitty will deduct points once you submit more than 40 times.
6. Q: If I fill in all the words in the grid and there are still some empty slots, what characters do I fill in the these extra spaces?
A: You can fill in any lower case letter there and make sure it doesn't introduce a forbidden word. A single letter gives you one solution; replacing it with another letter would give you another solution, and in total, this would lead to 26 potential solutions, since there are 26 lower case letters.
7. Q: What bonus do I get if my program ranks higher than the instructor's program on the leaderboard?
A: If by Thursday night 10pm (which is the submission deadline), your program ranks higher than the instructor's program, you have many options. You can choose one of these:
- Drop the lowest test score
- Drop the lowest homework
- Skip 1 future homework
- Skip test 3
You will receive an email asking you about which option you want to choose, or if you want to propose a different option.
## Rubric
@@ -90,15 +107,16 @@ You must do this assignment on your own, as described in the [Collaboration Poli
- One of name, collaborators, or hours not filled in. (-1)
- Two or more of name, collaborators, or hours not filled in. (-2)
- No reflection. (-1)
- LETTER GRID REPRESENTATION (2 pts)
- Grid is not represented via nested structure vector&lt;vector&lt;char&gt;&gt;, vector&lt;vector&lt;string&gt;&gt;, vector&lt;string&gt;, char\*\*, etc. (-1)
<!-- - LETTER GRID REPRESENTATION (3 pts)
- Grid is not represented via nested structure vector&lt;vector&lt;char&gt;&gt;, vector&lt;vector&lt;string&gt;&gt;, vector&lt;string&gt;, char\*\*, etc. (-2)
- Lookup of a position is not O(1), uses something like&lt;list&lt;char&gt;&gt; which has lookup of O(n). (-1)
- Incomplete to the point that no grid representation is evident within their code. (-1)
- USES RECURSION (4 pts)
- Use some non-trivial recursion but doesnt use recursion in the search process of board creation. (-2)
- Uses recursion but only trivially. (-3)
- Does not use any recursion. (-4)
- ALGORITHM ANALYSIS (In terms of the grid dimensions, the # of words, # of letters per word, the number of solutions etc. Looking for both an answer in order notation and a well-written justification in the plaintext README.txt file.) (5 pts)
- Incomplete to the point that no grid representation is evident within their code. (-2)
-->
- USES RECURSION (10 pts)
- Use some non-trivial recursion but doesnt use recursion in the search process of board creation. (-3)
- Uses recursion but only trivially. (-7)
- Does not use any recursion. (-10)
<!-- - ALGORITHM ANALYSIS (In terms of the grid dimensions, the # of words, # of letters per word, the number of solutions etc. Looking for both an answer in order notation and a well-written justification in the plaintext README.txt file.) (5 pts)
- No order notation provided (-5)
- Order notation not written in terms of the provided variables w,h,r,f,l,s. Introduces new vars or provides it just in terms of n. (-2)
- Incorrect order notation. (-2)
@@ -108,19 +126,16 @@ You must do this assignment on your own, as described in the [Collaboration Poli
- Did not finish but provides a reasonable analysis with respect to a theoretical implementation and properly justifies it. (-2)
- Did not finish but provides a runtime and some small analysis for a theoretical solution. (-4)
- Correct order notation for a largely incomplete implementation. (-4)
<!-- - TESTING SUMMARY & NEW TEST CASES (Included with submission and discussed in README.txt) (3 pts)
- TESTING SUMMARY & NEW TEST CASES (Included with submission and discussed in README.txt) (3 pts)
- Does not provide an adequate description of what the new testcases were in the README. (-2)
- Did not provide running times of the new test cases. (-1)
- Provides new test case description but implementation/test was missing from the submission. (-1)
- Did not provide new test cases or implementation too incomplete for new test cases. (-3)-->
- PROGRAM STRUCTURE (6 pts)
- PROGRAM STRUCTURE (7 pts)
- Putting almost everything in the main function. It's better to create separate functions for different tasks. (-2)
- Function bodies containing more than one statement are placed in the .h file. (okay for templated classes) (-2)
- Missing include guards in the .h file. (Or does not declare them correctly) (-1)
- Functions are not well documented or are poorly commented, in either the .h or the .cpp file. (-1)
- Improper uses or omissions of const and reference. (-1)
- At least one function is excessively long (i.e., more than 200 lines). (-1)
- Overly cramped, excessive whitespace, or poor indentation. (-1)
- Poor file organization: Puts more than one class in a file (okay for very small helper classes) (-1)
- Poor variable names. (-1)
- Contains useless comments like commented-out code, terminal commands, or silly notes. (-1)
- Poor choice of variable names: non-descriptive names (e.g. 'vec', 'str', 'var'), single-letter variable names (except single loop counter), etc. (-2)

View File

@@ -18,13 +18,6 @@ own, as described in "Academic Integrity for Homework" handout.
ESTIMATE OF # OF HOURS SPENT ON THIS ASSIGNMENT: < insert # hours >
ALGORITHM ANALYSIS:
What's the order notation of your algorithm?
MISC. COMMENTS TO GRADER:
Optional, please be concise!

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -0,0 +1,4 @@
3 2
+ cat
+ one
- on

View File

@@ -0,0 +1,13 @@
7 6
+ chore
+ anchor
+ horse
+ melee
+ wear
+ beast
+ oboe
+ bow
+ bottle
+ beaches
+ laser
+ wobbler

View File

@@ -0,0 +1,22 @@
15 3
+ aardvark
+ lilith
+ amount
+ tilde
+ true
+ bore
+ loud
+ illicit
+ lll
+ aaa
+ ama
+ aba
- hat
- bh
- el
- al
- ul
- at
- vo
- ve
- vb

View File

@@ -0,0 +1,12 @@
7 5
+ beans
+ erasing
+ amaze
+ arm
+ soapy
+ moo
+ normal
+ sling
+ bakes
+ go
+ gang

View File

@@ -0,0 +1,17 @@
5 9
+ wacky
+ wednesday
+ deans
+ sear
+ youre
+ ode
+ random
+ mosh
+ shado
+ mean
+ moose
+ sombody
+ kalm
+ sake
+ old
+ code

View File

@@ -0,0 +1,17 @@
10 5
+ fiery
+ human
+ alien
+ incredible
+ ship
+ pea
+ patron
+ nepal
+ retry
+ rap
+ aesh
+ shapes
+ cram
+ herse
+ minas
+ semen

View File

@@ -0,0 +1,25 @@
4 2
+ pin
+ pine
+ nip
+ ink
- a
- b
- c
- d
- f
- g
- h
- j
- l
- m
- o
- q
- r
- s
- t
- x
- v
- w
- y
- z

View File

@@ -1,4 +1,4 @@
# Lab 9 — Maps
# Lab 7 — Maps
This lab gives you practice initial practice in working with the STL associative container, maps. No downloads
are needed until Checkpoint 3.

View File

@@ -259,9 +259,71 @@ int main() {
You can compile and run this above [program](queue.cpp).
## 14.3 Leetcode Exercises
## 14.3 Stack Example Problem
Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
An input string is valid if:
- Open brackets must be closed by the same type of brackets.
- Open brackets must be closed in the correct order.
- Every close bracket has a corresponding open bracket of the same type.
Example 1: Input: s = "()" Output: true
Example 2: Input: s = "()[]{}" Output: true
Example 3: Input: s = "(]" Output: false
Example 4: Input: s = "([])" Output: true
Constraints: 1 <= s.length <= 104; s consists of parentheses only '()[]{}'.
We have the solution here:
```cpp
bool isValid(string s) {
std::stack<char> myStack;
int len = s.length();
char c;
for(int i=0;i<len;i++){
// push all the open brackets into the stack
if(s[i]=='(' || s[i]=='{' || s[i]=='['){
myStack.push(s[i]);
}else{
// if we encounter a close bracket first, it's already invalid.
if(myStack.empty()){
return false;
}
c = myStack.top();
myStack.pop();
// for every close bracket we encounter, there must be a corresponding open bracket at the top of the stack.
if(s[i]==')' && c!='('){
return false;
}
if(s[i]=='}' && c!='{'){
return false;
}
if(s[i]==']' && c!='['){
return false;
}
}
}
// if it's empty, we are good.
if(myStack.empty()){
return true;
}else{
return false;
}
}
```
<!-- - [Leetcode problem 20: Valid Parentheses](https://leetcode.com/problems/valid-parentheses/). Solution: [p20_valid_parentheses.cpp](../../leetcode/p20_valid_parentheses.cpp) -->
- Play this [animation](https://jidongxiao.github.io/CSCI1200-DataStructures/animations/stack/index.html) to see how this program works.
## 14.4 More Leetcode Exercises
- [Leetcode problem 225: Implement Stack using Queues](https://leetcode.com/problems/implement-stack-using-queues/). Solution: [p225_stack_using_queues.cpp](../../leetcode/p225_stack_using_queues.cpp).
- [Leetcode problem 232: Implement Queue using Stacks](https://leetcode.com/problems/implement-queue-using-stacks/). Solution: [p232_queue_using_stacks.cpp](../../leetcode/p232_queue_using_stacks.cpp).
- [Leetcode problem 20: Valid Parentheses](https://leetcode.com/problems/valid-parentheses/). Solution: [p20_valid_parentheses.cpp](../../leetcode/p20_valid_parentheses.cpp)
- [Leetcode problem 71: Simplify Path](https://leetcode.com/problems/simplify-path/). Solution: [p71_simplify_path.cpp](../../leetcode/p71_simplify_path.cpp)

View File

@@ -1,41 +1,81 @@
# Lecture 15 --- Associative Containers (Maps), Part 1
Associative Containers (STL Maps)
- STL Pairs
- STL Maps: associative containers for fast insert, access and remove
- Example: Counting word occurrences
- STL Pairs
- Map iterators
- Map member functions: operator[], find, insert, erase.
- Efficiency
- STL maps vs. STL vectors vs. STL lists
## 15.1 STL Maps: Associative Containers
## 15.1 STL Pairs
- std::pair is a templated struct with just two members, called first and second.
```cpp
template <typename T1, typename T2>
struct pair {
T1 first;
T2 second;
// Constructors
constexpr pair();
constexpr pair(const T1& x, const T2& y);
// Other member functions...
};
```
**struct** in C++ is identical to class except that members are public by default, std::pair is implemented as a struct to allow direct access to its first and second members without requiring explicit getter functions.
- To work with pairs, you must #include &lt;utility&gt;. Note that the header file for maps (#include &lt;map&gt;) itself includes utility, so you don't have to include utility explicitly when you use pairs with maps.
- Here are simple examples of manipulating pairs:
```cpp
std::pair<int, double> p1(5, 7.5);
std::pair<int, double> p2 = std::make_pair(8, 9.5);
p1.first = p2.first;
p2.second = 13.3;
std::cout << p1.first << " " << p1.second << std::endl;
std::cout << p2.first << " " << p2.second << std::endl;
p1 = p2;
std::pair<const std::string, double> p3 = std::make_pair(std::string("hello"), 3.5);
p3.second = -1.5;
// p3.first = std::string("illegal"); // (a)
// p1 = p3; // (b)
```
- The function std::make_pair creates a pair object from the given values. It is really just a simplified
constructor, and as the example shows there are other ways of constructing pairs.
- Most of the statements in the above code show accessing and changing values in pairs.
The two statements at the end are commented out because they cause syntax errors:
- In (a), the first entry of p3 is const, which means it cant be changed.
- In (b), the two pairs are different types! Make sure you understand this.
## 15.2 STL Maps: Associative Containers
- STL maps store pairs of “associated” values.
We will see several examples today, in Lab 9, and in Lecture 16:
- An association between a string, representing a word, and an int representing the number of times that
- e.g., An association between a string, representing a word, and an int representing the number of times that
word has been seen in an input file.
- An association between a string, representing a word, and a vector that stores the line numbers from a
text file on which that string occurs (next lecture).
- An association between a phone number and the name of the person with that number (Lab 9).
- An association between a class object representing a student name and the students info (next lecture).
- e.g., An association between a string, representing a word, and a vector that stores the line numbers from a
text file on which that string occurs.
- e.g., An association between a phone number and the name of the person with that number.
- e.g., An association between a class object representing a student name and the students info.
A particular instance of a map is defined (declared) with the syntax:
std::map&lt;key_type, value_type&gt; var_name
In our first two examples above, key type is a string. In the first example, the value type is an int and in
```cpp
std::map<key_type, value_type> var_name
```
- In our first two examples above, key type is a string. In the first example, the value type is an int and in
the second it is a std::vector&lt;int&gt;.
- Entries in maps are pairs: std::pair&lt;const key_type, value_type&gt;, or just std::pair&lt;key_type, value_type&gt;.
- Entries in maps are pairs: std::pair&lt;const key_type, value_type&gt;, the const is needed to ensure that the keys arent changed! This is crucial because maps are sorted by keys!
- Map iterators refer to pairs.
- Map search, insert and erase are all very fast: O(log n) time, where n is the number of pairs stored in the map.
Note: The STL map type has similarities to the Python dictionary, Java HashMap, or a Perl hash, but the
<!-- Note: The STL map type has similarities to the Python dictionary, Java HashMap, or a Perl hash, but the
data structures are not the same. The organization, implementation, and performance is different. In a couple
weeks well see an STL data structure that is even more similar to the Python dictionary.
- Map search, insert and erase are O(log n).
First, lets see how some of this works with a program to count the occurrences of each word in a file. Well look
at more details and more examples later.
weeks well see an STL data structure that is even more similar to the Python dictionary.-->
## 15.2 Counting Word Occurrences
## 15.3 Counting Word Occurrences
Heres a simple and elegant solution to this problem using a map:
First, lets see how some of this works with a program to count the occurrences of each word in a file. Heres a simple and elegant solution to this problem using a map:
```cpp
#include <iostream>
@@ -65,37 +105,6 @@ must be an operator< defined for the key.
changed. It can only be erased (together with the associated value).
- Duplicate keys can not be in the map.
## 15.4 STL Pairs
The mechanics of using std::pairs are relatively straightforward:
- std::pairs are a templated struct with just two members, called first and second. Reminder: a struct
is basically a wimpy class.
- To work with pairs, you must #include &lt;utility&gt;. Note that the header file for maps (#include &lt;map&gt;)
itself includes utility, so you dont have to include utility explicitly when you use pairs with maps.
- Here are simple examples of manipulating pairs:
```cpp
std::pair<int, double> p1(5, 7.5);
std::pair<int, double> p2 = std::make_pair(8, 9.5);
p1.first = p2.first;
p2.second = 13.3;
std::cout << p1.first << " " << p1.second << std::endl;
std::cout << p2.first << " " << p2.second << std::endl;
p1 = p2;
std::pair<const std::string, double> p3 = std::make_pair(std::string("hello"), 3.5);
p3.second = -1.5;
// p3.first = std::string("illegal"); // (a)
// p1 = p3; // (b)
```
- The function std::make_pair creates a pair object from the given values. It is really just a simplified
constructor, and as the example shows there are other ways of constructing pairs.
- Most of the statements in the above code show accessing and changing values in pairs.
The two statements at the end are commented out because they cause syntax errors:
- In (a), the first entry of p3 is const, which means it cant be changed.
- In (b), the two pairs are different types! Make sure you understand this.
- Returning to maps, each entry in the map is a pair object of type:
std::pair&lt;const key_type, value_type&gt;
- The const is needed to ensure that the keys arent changed! This is crucial because maps are sorted by keys!
## 15.5 Maps: operator[]
- Weve used the [] operator on vectors, which is conceptually very simple because vectors are just resizable
@@ -161,9 +170,71 @@ up to, but not including, last.
- size_type erase(const key_type& k) — erase the pair containing key k, returning either 0 or 1, depending
on whether or not the key was in a pair in the map.
## 15.10 Leetcode Exercises
## 15.10 Leetcode Exercise
Given an integer array nums and an integer k, return true if there are two distinct indices i and j in the array such that nums[i] == nums[j] and abs(i - j) <= k.
We have the solution below.
```cpp
#include <iostream>
#include <vector>
#include <map>
bool containsNearbyDuplicate(std::vector<int>& nums, int k) {
int size = nums.size();
// create the map, map key is the value of the vector element, map value is the index of that element in the vector.
std::map<int,int> map1;
for(int i=0;i<size;i++){
// if already exists
if(map1.find(nums[i])!=map1.end()){
if(i-map1[nums[i]]<=k){
return true;
}
}
map1[nums[i]]=i;
}
return false;
}
int main() {
std::vector<std::vector<int>> testCases = {
{1, 2, 3, 1}, // Expected: true (nums[0] == nums[3], abs(0-3) <= k)
{1, 0, 1, 1}, // Expected: true (nums[2] == nums[3], abs(2-3) <= k)
{1, 2, 3, 4, 5}, // Expected: false (no duplicates)
{1, 2, 3, 4, 1}, // Expected: true if k >= 4
{99, 99}, // Expected: true if k >= 1
{1, 2, 3, 4, 5, 6}, // Expected: false (no duplicates)
};
std::vector<int> kValues = {3, 1, 2, 4, 1, 2}; // Corresponding k values for test cases
for (size_t i = 0; i < testCases.size(); i++) {
std::cout << "Test Case " << i + 1 << ": ";
bool result = containsNearbyDuplicate(testCases[i], kValues[i]);
std::cout << (result ? "true" : "false") << std::endl;
}
return 0;
}
```
When running the above program, we get:
```console
$ ./a.out
Test Case 1: true
Test Case 2: true
Test Case 3: false
Test Case 4: true
Test Case 5: true
Test Case 6: false
```
You can also find this problem on Leetcode.
- [Leetcode problem 219: Contains Duplicate II](https://leetcode.com/problems/contains-duplicate-ii/description/). Solution: [p219_contains_duplicate_ii.cpp](../../leetcode/p219_contains_duplicate_ii.cpp).
## 15.11 More Leetcode Exercises
- [Leetcode problem 1: Two Sum](https://leetcode.com/problems/two-sum/). Solution: [p1_twosum.cpp](../../leetcode/p1_twosum.cpp).
- [Leetcode problem 219: Contains Duplicate II](https://leetcode.com/problems/contains-duplicate-ii/description/). Solution: [p219_contains_duplicate_ii.cpp](../../leetcode/p219_contains_duplicate_ii.cpp).
- [Leetcode problem 290: Word Pattern](https://leetcode.com/problems/word-pattern/). Solution: [p290_word_pattern.cpp](../../leetcode/p290_word_pattern.cpp).

View File

@@ -0,0 +1,40 @@
#include <iostream>
#include <vector>
#include <map>
bool containsNearbyDuplicate(std::vector<int>& nums, int k) {
int size = nums.size();
// create the map, map key is the value of the vector element, map value is the index of that element in the vector.
std::map<int,int> map1;
for(int i=0;i<size;i++){
// if already exists
if(map1.find(nums[i])!=map1.end()){
if(i-map1[nums[i]]<=k){
return true;
}
}
map1[nums[i]]=i;
}
return false;
}
int main() {
std::vector<std::vector<int>> testCases = {
{1, 2, 3, 1}, // Expected: true (nums[0] == nums[3], abs(0-3) <= k)
{1, 0, 1, 1}, // Expected: true (nums[2] == nums[3], abs(2-3) <= k)
{1, 2, 3, 4, 5}, // Expected: false (no duplicates)
{1, 2, 3, 4, 1}, // Expected: true if k >= 4
{99, 99}, // Expected: true if k >= 1
{1, 2, 3, 4, 5, 6}, // Expected: false (no duplicates)
};
std::vector<int> kValues = {3, 1, 2, 4, 1, 2}; // Corresponding k values for test cases
for (size_t i = 0; i < testCases.size(); i++) {
std::cout << "Test Case " << i + 1 << ": ";
bool result = containsNearbyDuplicate(testCases[i], kValues[i]);
std::cout << (result ? "true" : "false") << std::endl;
}
return 0;
}

View File

@@ -1,6 +1,20 @@
# Lecture 16 --- Associative Containers (Maps), Part 2
## 16.1 More Complicated Values
## 16.1 Map Insert Performance
One way to improve the map insert performance is using the move constructor. Read [this document](../optimization/map_insert).
## 16.2 Map Erase Performance
We learned from previous lecture that we can erase an element from a map via the erase function, and there are two formats:
- void erase(iterator p) — erase the pair referred to by iterator p.
- size_type erase(const key_type& k) — erase the pair containing key k, returning either 0 or 1, depending on whether or not the key was in a pair in the map.
But there is a performance difference between these two. Read [this document](../optimization/map_erase/).
## 16.3 More Complicated Values
- Lets look at the example:
```cpp
@@ -41,7 +55,7 @@ use of push back or through construction of the vector).
- We can figure out the correct syntax for all of these by drawing pictures to visualize the contents of the map
and the pairs stored in the map. We will do this during lecture, and you should do so all the time in practice.
## 16.2 Typedefs
## 16.5 Typedefs
- One of the painful aspects of using maps is the syntax. For example, consider a constant iterator in a map
associating strings and vectors of ints:
@@ -65,7 +79,7 @@ map_vect :: const_iterator p;
The compiler makes the substitution for you.
## 16.3 Standard Library Sets
## 16.6 Standard Library Sets
- STL sets are ordered containers storing unique “keys”. An ordering relation on the keys, which defaults to
operator<, is necessary. Because STL sets are ordered, they are technically not traditional mathematical sets.
@@ -79,12 +93,12 @@ you shouldn't use [] to access elements in a set.
#include <set>
```
## 16.4 Leetcode Exercises (Maps)
## 16.7 Leetcode Exercises (Maps)
- [Leetcode problem 49: Group Anagrams](https://leetcode.com/problems/group-anagrams/). Solution: [p49_group_anagrams.cpp](../../leetcode/p49_group_anagrams.cpp).
- [Leetcode problem 290: Word Pattern](https://leetcode.com/problems/word-pattern/). Solution: [p290_word_pattern.cpp](../../leetcode/p290_word_pattern.cpp).
## 16.5 Leetcode Exercises (Sets)
## 16.8 Leetcode Exercises (Sets)
- [Leetcode problem 414: Third Maximum Number](https://leetcode.com/problems/third-maximum-number/). Solution: [p414_third_max_number.cpp](../../leetcode/p414_third_max_number.cpp).
- [Leetcode problem 1207: Unique Number of Occurrences](https://leetcode.com/problems/unique-number-of-occurrences/). Solution: [p1207_unique_number_occurrences.cpp](../../leetcode/p1207_unique_number_occurrences.cpp).

View File

@@ -0,0 +1,69 @@
# `erase by iterator` vs. `erase by key` in C++
## Overview
erasing by iterator in std::maps is typically faster than erasing by key.
## Erasing by Iterator:
- When you erase an element using an iterator, the map already has a direct reference to the node that contains the element to be erased.
- The iterator is a pointer to the element (node) in the underlying tree structure (which is usually a red-black tree for std::map).
## Erasing by Key:
- When you erase an element by key, std::map first has to search for the key.
- It does this by traversing the red-black tree to find the node that matches the key.
- After finding the node, it performs the same operation as erase(iterator), but since it had to perform a search to locate the key, this is slower than directly accessing the iterator.
## Benchmarks
Compile and run these 2 programs to see the performance difference.
[map_erase_slow.cpp](map_erase_slow.cpp) [map_erase_fast.cpp](map_erase_fast.cpp)
Both programs just create a map containing 1 millions integers, and then erase these 1 millions integers. As can be seen from the following results, erasing by iterators is much faster than erasing by key.
```console
$g++ map_erase_slow.cpp -o map_erase_slow
$g++ map_erase_fast.cpp -o map_erase_fast
$time ./map_erase_slow
real 0m0.640s
user 0m0.624s
sys 0m0.016s
$time ./map_erase_fast
real 0m0.406s
user 0m0.386s
sys 0m0.020s
$time ./map_erase_fast
real 0m0.382s
user 0m0.374s
sys 0m0.008s
$time ./map_erase_slow
real 0m0.629s
user 0m0.617s
sys 0m0.012s
$time ./map_erase_slow
real 0m0.632s
user 0m0.623s
sys 0m0.009s
$time ./map_erase_fast
real 0m0.383s
user 0m0.366s
sys 0m0.017s
```

View File

@@ -0,0 +1,20 @@
#include <iostream>
#include <map>
int main() {
const int N = 1000000;
std::map<int, int> m;
// fill the map with some values
for (int i = 0; i < N; ++i) {
m[i] = i;
}
// erase all elements using iterators
for (std::map<int, int>::iterator itr = m.begin(); itr != m.end(); ) {
itr = m.erase(itr); // erase using iterator and move to the next element
}
return 0;
}

View File

@@ -0,0 +1,20 @@
#include <iostream>
#include <map>
int main() {
const int N = 1000000;
std::map<int, int> m;
// fill the map with some values
for (int i = 0; i < N; ++i) {
m[i] = i;
}
// erase by key
for (int i = 0; i < N; ++i) {
m.erase(i);
}
return 0;
}

View File

@@ -0,0 +1,72 @@
# Using Move Constructors to Improve Performance in std::map::insert
When working with std::map, understanding how move semantics improve performance can be crucial for optimizing memory management and overall efficiency. The move constructor is an essential tool in this process, especially in the context of inserting elements into a std::map.
## Basic Overview of std::map Insertions
A std::map is a sorted associative container that stores key-value pairs. The keys in a map are unique, and they are automatically sorted according to a comparison function. When you insert elements into a map using insert or emplace, the container must allocate memory and potentially rearrange internal data structures to maintain the map's properties.
The insert operation typically involves:
- Creating a new key-value pair.
- Inserting it into the internal tree structure (typically a Red-Black tree).
- If an object is inserted into a map, it may need to be copied or moved, depending on the availability of move semantics and the state of the object being inserted.
## The Role of Move Constructors
- Move constructors provide a mechanism to transfer ownership of resources (like dynamically allocated memory) from one object to another, without the overhead of copying the data. In contrast, the copy constructor performs a deep copy, which involves duplicating all resources of the original object. For large objects, this can be slow and memory-intensive.
- A move constructor transfers the ownership of resources without allocating new memory, which is a much faster process compared to copying.
## How Move Constructors Improve std::map::insert Performance
When you insert an element as a a temporary object into a std::map using insert, the insert function will call the copy constructor; but if a move constructor exists, it will call the move constructor instead of the copy constructor. Since in the move constructor, a shallow copy occurs, it is faster than the copy constructor, which normally does a deep copy.
## Benchmarks
Compile and run these 2 programs to see the performance difference.
[map_insert_copy.cpp](map_insert_copy.cpp) [map_insert_move.cpp](map_insert_move.cpp)
Both programs just create a map and insert 10 elements (where the value is a large class object), the only difference between these two programs, is that the second program defines the move constructor where the first program does not define the move constructor. As can be seen from the following results, having the move constructor will improve the performance of the program.
```console
$g++ -o map_insert_copy map_insert_copy.cpp
$g++ -o map_insert_move map_insert_move.cpp
$time ./map_insert_copy
real 0m0.507s
user 0m0.247s
sys 0m0.259s
$time ./map_insert_copy
real 0m0.505s
user 0m0.208s
sys 0m0.297s
$time ./map_insert_move
real 0m0.290s
user 0m0.178s
sys 0m0.112s
$time ./map_insert_move
real 0m0.277s
user 0m0.176s
sys 0m0.101s
$time ./map_insert_copy
real 0m0.509s
user 0m0.248s
sys 0m0.261s
$time ./map_insert_move
real 0m0.282s
user 0m0.182s
sys 0m0.100s
```

View File

@@ -0,0 +1,41 @@
#include <iostream>
#include <map>
#include <vector>
#include <string>
class LargeClass {
public:
std::vector<int> data;
std::string name;
LargeClass(int size, const std::string& n) : data(size), name(n) {
// simulate work in the constructor
for (int i = 0; i < size; ++i) {
data[i] = i;
}
}
// define a copy constructor for demonstration purposes
LargeClass(const LargeClass& other) : data(other.data), name(other.name) {
// std::cout << "Copy constructor called\n";
}
// for demonstration, printing the object contents
void print() const {
std::cout << name << ": " << data[0] << "..." << data[data.size() - 1] << std::endl;
}
};
int main() {
const int num_elements = 10000000;
const int map_size = 10;
std::map<int, LargeClass> map_insert;
for (int i = 0; i < map_size; ++i) {
map_insert.insert({i, LargeClass(num_elements, "Insert_" + std::to_string(i))});
}
return 0;
}

View File

@@ -0,0 +1,46 @@
#include <iostream>
#include <map>
#include <vector>
#include <string>
class LargeClass {
public:
std::vector<int> data;
std::string name;
LargeClass(int size, const std::string& n) : data(size), name(n) {
// simulate work in the constructor
for (int i = 0; i < size; ++i) {
data[i] = i;
}
}
// define a copy constructor for demonstration purposes
LargeClass(const LargeClass& other) : data(other.data), name(other.name) {
// std::cout << "Copy constructor called\n";
}
// define a move constructor
LargeClass(LargeClass&& other) noexcept : data(std::move(other.data)), name(std::move(other.name)) {
// std::cout << "Move constructor called\n";
}
// for demonstration, printing the object contents
void print() const {
std::cout << name << ": " << data[0] << "..." << data[data.size() - 1] << std::endl;
}
};
int main() {
const int num_elements = 10000000;
const int map_size = 10;
std::map<int, LargeClass> map_insert;
for (int i = 0; i < map_size; ++i) {
map_insert.insert({i, LargeClass(num_elements, "Insert_" + std::to_string(i))});
}
return 0;
}