Agent Work: Prime Factors
Claude Opus 4.6 · COMP 321: Introduction to Computer Systems
COMP 321: Introduction to Computer Systems
Project 1: Factors
Overview
You will write C code to count the prime factors of a number. The goals of this project are as follows:
- Write a small amount of C code.
- Become familiar with compiling C code.
- Understand the perils of writing a deeply recursive program.
Summary
You will write three versions of code to count the prime factors of a positive integer greater than one (Please remember, "1" is NOT a prime number):
- Count all of the prime factors recursively. For example, 12 has 3 prime factors: 2, 2, and 3.
- Count all of the prime factors iteratively.
- Count the distinct prime factors iteratively. For example, 12 has 2 distinct prime factors: 2 and 3.
You will write a different procedure to handle each version. You do not need to write a particularly efficient program, although it should complete in sixty seconds on any input. In particular, a truly efficient version would use some data structure to store previously discovered primes, but you have not yet learned about data structures in C.
You will not write an entire program. We provide a basic main function to handle the I/O. First, you will write a recursive solution, but this solution might not work for certain large inputs, for example, 2,000,000,001. Second, you will write an iterative solution that is guaranteed to work for all valid inputs.
Deeply Recursive Programs
When a function is called from a C program, it is allocated memory to store its parameters and local variables. This allocation typically occurs on a region called the *program stack*. You will learn more about program stacks later in the semester.
A recursive function is one that calls itself repeatedly until some condition is satisfied. Depending on how deep the recursion is, the program stack may consume a lot of memory. Eventually the program will run out of memory and crash. For example, a very simple recursive solution to count all prime factors is likely to crash with certain large inputs, for example, 2,000,000,001. You should learn to write programs which efficiently use their stack. This is especially important if the program will be executed on a platform with limited memory, such as embedded systems or mobile phones. In this assignment, you have to write both a recursive solution (that does not have to work on all inputs) and an iterative solution that uses the stack efficiently and works for all valid inputs. A valid input is any number that can be represented by an unsigned int.
The limit command can be used to check and change the maximum stack size which can be allocated by your program. The default maximum stack size per program is 8 MB and your solution will be graded using only that default size.
Notes
- The compiler generates warnings for a reason. You should fix any code that generates a warning to minimize the chances of bugs. Experienced C programmers may understand what they are doing well enough to decide that a warning is unimportant. However, code that causes warnings can be an indication of actual program errors, so it is a good idea to fix any code that causes a warning regardless of your experience level. Your code should compile without any warnings. (We will use the
-Walland-Wextraflags to cc.)
- Testing is critical in all programming. You need to be sure to comprehensively test the procedures that you write.
- We provide a main function that you must not change. However, when
-tis specified on the command line, the functiontest_factorswill be called with no arguments instead of running the program normally. You may put whatever testing code you would like in this function. We will not use the-targument when grading your program, so this is solely for you to use in your testing as you see fit.
- When
-ris specified on the command line, the functioncount_factors_recursivewill be called. This function should have a recursive implementation. You must not usefororwhileloops in its implementation. You may write helper functions, as needed, but they too must not use any loops. As previously discussed, this function does not need to handle all inputs without crashing due to stack overflow. (That said, it is fine if you are able to design an implementation that does handle all inputs without crashing).
- You may also find it helpful to use some simple
printfstatements within your procedures to see intermediate values during the execution of your program as you are testing and debugging your code. Theprintfstatement in C has a format string followed by a list of zero or more additional arguments. The "%" characters in the format string specify the locations in the output where the additional arguments must be printed, and the character following each "%" must match the type of the corresponding argument toprintf. For example, a single unsigned integer can be printed in C usingprintfas follows:
``c
printf("Print an unsigned int, %u, between the commas.\n", number);
``
You can also learn from the other printf statements in the code given to you. Using printf statements is an effective method of debugging simple programs and for narrowing down errors in more complex programs. However, make sure that you comment out all such printf statements when you are done, as the final program should only perform the input and output that is provided in the main function.
- Use requires/effects comments for each procedure, as in the provided code. These procedure comments should be about *what* the procedure does, not *how* it does it. In other words, a procedure
summight have the following effects: *Returns the sum of the elements in the array.* An inappropriate comment would be: *loops over the elements in the array using a for loop, adds each element to a running sum, and then returns the running sum after the for loop completes.* Comments inside the procedure can be used to document what the procedure is doing when the code is not relatively obvious. However, commenting the statementi += 1;with "Add one to i." is pointless. It is only adding clutter to your program.
- When you are modifying an existing program, *the first and foremost rule of good coding style* is that the style of your code, e.g., its indentation, should match the style of the surrounding code. In effect, it should not be obvious to a reader where different people have edited the code. Also, keep in mind that if you consistently indent your code, it will make it easier for someone else to understand your code.
Files
You should see the following files in your workspace:
factors.c- provided code (implement your solution here)Makefile- specification for building factors using makewriteup.md- a skeleton writeup fileinstructions.md- this file
Compiling and Running Your Code
To compile your code, use the Unix command:
makeThis will compile your code producing an executable file named factors. This file can then be run to determine the number of prime factors of 12 as follows:
./factors
Enter number:
12
12 has 3 prime factors, 2 of them distinct.Since a prime number's only prime factor is the number itself, inputting a prime number, such as 13, should produce output like:
13 has 1 prime factors, 1 of them distinct.Make sure that the iterative version of your program works for all valid inputs. However, the recursive version of your program may crash with large inputs. For example, on executing the recursive solution to count all prime factors with input 2,000,000,001, the following will likely occur:
./factors -r
Enter number:
2000000001
Segmentation fault (core dumped)Your program must only handle valid inputs. If an invalid input is given to your program, it is acceptable for your program to output nonsense. In addition, it is acceptable for the recursive version of your program to crash due to stack overflow on large valid inputs.
Testing
Use the grade tool to run the automated test suite:
# From the workspace directory
bin/grade .
# Or specify the workspace path
bin/grade ./workspaces/agent_factorsThe grade tool will compile your code and run all tests, showing which pass and fail. Focus on getting all tests to pass.
--- *COMP 321: Introduction to Computer Systems, Rice University, Spring 2024*
BSCS Bench