What is the formula to calculate this sequence? - c

I've been facing a problem with this particular question in C.
The question is:
Write a program to generate the first n terms in the series --- 2,5,9,..,20,27
I'm stuck in the for-loop part. Like, for other terms
example: series --- 5,9,17,29,45,...
I can calculate the remaining series by the formula:
for(i=0; i<n; i++)
{
a=a+(4*i); //a is initialized to 5
printf("%d", a);
}
Thank you.

It looks like the (i+1)-st element is created from the i-th by adding an increasing number:
a0 = 2, d0 = 3
a1 = 2+3 = 5, d0 = 4
a2 = 5+4 = 9, d0 = 5
a3 = 9+5 = 14, d0 = 6
a4 = 14+6= 20, d0 = 7
a5 = 20+7= 27, d0 = 8
...and so on
You can compute this result by incrementing d as you walk through the loop, and adding it to the previous value of a.
According to the Online Encyclopedia of Integer Sequences, elements of this sequence could be computed using this closed-form expression:
n*(n+3)/2
Note: The above division always produces an integer value because one of n or n+3 will be even.

Is this what you expect?
#include <stdio.h>
int main(void)
{
int a = 2, n = 10;
for(int i = 0; i < n; i++)
{
printf("%d, ", a);
a = a + i + 3;
}
printf("etc\n");
return 0;
}
Output
$ gcc main.c -o main.exe; ./main.exe;
2, 5, 9, 14, 20, 27, 35, 44, 54, 65, etc

If I understand you correctly you're looking for
a=2;
n=5; /* to generate numbers up to 27 */
for (i=3;i<n+3;i++)
{
a+=i;
printf("%d",a);
}
It's n+3 because you would begin with 3 and count n times up from there.

Related

How can I get the index of a given combination?

I have a sequence of arrays of numbers with 5 elements each, from 0 to 8, and I have to order than using that combination, I mean:
i=0, {0,0,0,0,0}
i=1, {0,0,0,0,1}
i=2, {0,0,0,0,2}
i=3, {0,0,0,0,3}
i=4, {0,0,0,0,4}
i=5, {0,0,0,0,5}
i=6, {0,0,0,0,6}
i=7, {0,0,0,0,7}
i=8, {0,0,0,0,8}
i=9, {0,0,0,1,1}
...
i=1285, {7,8,8,8,8}
i=1286, {8,8,8,8,8}
so if I give {0,0,1,1,2} to the function it's returns 7.
I thought about using the Combinatorial number system
but I'm missing something that I don't know what it is, the code below just doesn't work
#include <stdio.h>
#include <stdlib.h>
#define size 1287
int combination[9][5] = {
{0, 0, 0, 0, 0},
{1, 1, 1, 1, 1},
{2, 3, 4, 5, 6},
{3, 3, 6, 15, 21},
{4, 10, 20, 35, 56},
{5, 15, 35, 70, 126},
{6, 21, 56, 126, 252},
{7, 28, 84, 210, 462},
{8, 36, 120, 330, 792}
};
int getKey(int array[]){
int key=0;
int tempArray[9] = {0};
for(int i=0;i<5;i++){
tempArray[array[i]]++;
}
int j=0;
for(int i=0;i<9;i++){
if(tempArray[i]!=0){
while(tempArray[i]!=0){
array[j++] = i;
key += combination[i][5-j];
tempArray[i]--;
}
}
}
return key;
}
int main(){
int it[5];
for(it[0] = 0 ;it[0]<9;it[0]++){
for(it[1]=it[0];it[1]<9;it[1]++){
for(it[2]=it[1];it[2]<9;it[2]++){
for(it[3]=it[2];it[3]<9;it[3]++){
for(it[4]=it[3];it[4]<9;it[4]++){
printf("{%d %d %d %d %d} = %d\n",it[0],it[1],it[2],it[3],it[4],getKey(it));
}
}
}
}
}
return 0;
}
Obs: I'm using counting sort to keep the lexicographic order, in theory I will receive unsorted arrays.
I will give you the Answer I wrote for the previous version of this question which you posted yesterday and deleted. (And that's bad form, by the way.)
Let's call the binomial coefficient C(n, k) = n!/(k!(n-k)!)
The number of unordered strings of m letters drawn from an alphabet of s symbols is C(m+s-1, s-1). Let's call that D(m, s). In this case, D(5, 9) = C(5+9-1, 9-1) = C(13, 8) = 1287
Let's sort each string, then number them:
aaaaa 1
aaaab 2
aaaac 3
...
aaaai 9
aaabb 10
aaabc 11
...
If a string contains 5 a's, its number is D(5, 1) = C(5+1-1, 1-1) = C(5, 0) = 1.
If a string contains 4 a's, its number is 1 plus a number determined by the non-a letter, which goes up to D(1,8) = C(1+8-1,8-1) = C(8, 7) = 8. So they go up to 1+8=9.
If a string contains 3 a's, its number is 9 plus a number determined by the non-a letters, which goes up to D(2,8) = C(9,7) = 36, so 9+36=45.
If a string contains 2 a's, its number is in [46,165].
If a string contains 1 a, its number is in [166, 495].
If a string contains no a, its number is in [496, 1287].
So how about the string "aabgg"? It's number is (45)+(8)+(7)+(6)+(5)+(4)+(1)=76
No collisions, and the calculation of the index is O(sm(s+m)), which is not too bad for m=5 and s=9.
EDIT: to clarify, let's define
E(j, m, s) = D(0,s-1)+D(1,s-1)+...+D(m-j-1,s-1)
Suppose a string of m letters drawn from an alphabet of s symbols contains j of the first letter of the alphabet. There are E(j,m,s) strings in the catalogue before the first such string. For instance, before the first string that begins with exactly two a's ("aabbb"), there are E(2, 5, 9)=45 strings.
To get to "aabbb" we must count out 45 strings.
To get from "aabbb" to the next string that contains exactly one b ("aabcc"), we must count out E(1, 3, 8) = 8 strings.
From there to the next string that contains no c ("aabdd"), E(0, 2, 7) = 7 strings.
No d ("aabee"): E(0, 2, 6) = 6
No e ("aabff"): E(0, 2, 5) = 5
No f ("aabgg"): E(0, 2, 4) = 4
And we must count "aabgg" itself: 1
well, I think this look like oct number 1...8
0 = {00000}
1 = {00001}
2 = {00002}
8 = {00010}
if this what you mean
I think this algorithm is the best
int get_key(int a[5]){
int idx, rval=0;
for(i=4; i<=0; i--)
rval += powl(a[i], i);
return rval;
}

Weird results while printing elements of integer array

I just have to make a simple program, where I have an array given with random numbers, then I have to do some things with the array and then print the elements at the end. But I don't know what's happening here.
First I wanted to make a code, just to print the elements and see if it works before doing anything else.
#include <stdio.h>
int main(void) {
int nums[] = {12, 3, 54, -4, 56, 4, 7, 3};
//.....
for(int i = 0; nums[i]; i++) {
printf("nums[%d] = %d\n", i, nums[i]);
}
return 0;
}
And the result was:
nums[0] = 12
nums[1] = 3
nums[2] = 54
nums[3] = -4
nums[4] = 56
nums[5] = 4
nums[6] = 7
nums[7] = 3
nums[8] = -427200144
nums[9] = 32765
I ran the code more times, and the 8th and 9th element is always kinda random... But I mean I don't even have that many numbers, what's wrong here??
Also I tried with other random numbers and sometimes it works fine...
int nums[] = {2, -10, 64, 100, 22, 4};
nums[0] = 2
nums[1] = -10
nums[2] = 64
nums[3] = 100
nums[4] = 22
nums[5] = 4
Can someone explain what's happening here?
Edit: Meanwhile I realized this method is bad, since if the number in the array is 0, then my condition is false so the for cycle stops, but I'm curious, what's happening here, so I gonna post this anyways.
I recommend
for(int i = 0; i < sizeof(nums) / sizeof(*nums); i++) {
printf("nums[%d] = %d\n", i, nums[i]);
}
sizeof(nums) is the total size of the array (in bytes).
sizeof(*nums) is size of one element of the array (in bytes).
Therefore, sizeof(nums) / sizeof(*nums) represents the number of elements and that is what should be the condition in the loop.
Another option is having a separate variable that contains number of elements in the array, but it's less convenient than the first method I described.

Count ones in a segment (binary)

There is a problem which i am working on it right now and it's as the following :
there are two numbers x1 and x2 and x2 > x1.
for example x1 = 5; and x2 = 10;
and I must find the sum of ones between x1 and x2 in binary representations.
5 = 101 => 2 ones
6 = 110 => 2 ones
7 = 111 => 3 ones
8 = 1000 => 1 one
9 = 1001 => 2 ones
10= 1010 => 2 ones
so the sum will be
sum = 2 + 2 + 3 + 1 + 2 + 2 = 12 ones;
so I have managed to make a code without even transfer the numbers to binary and wasting execution time.
I noticed that the numbers of ones in every 2^n with n >= 1 is 1
Ex : 2^1 => num of ones is 1
2^2 => 1 2^15 => 1
you can test it here if you want: https://www.rapidtables.com/convert/number/decimal-to-binary.html?x=191
and between each 2^n and 2^(n+1) there are Consecutive numbers as you will see in this example :
num number of ones
2^4 = 16 1
17 2
18 2
19 3
20 2
21 3
22 3
23 4
24 2
25 3
26 3
27 4
28 3
29 4
30 4
31 5
2^5 = 32 1
so I write a code that can find how many ones between 2^n and 2^(n+1)
int t; ////turns
int bin = 1; //// numbers of ones in the binary format ,,, and 1 for 2^5
int n1 = 32; //// 2^5 this is just for clarification
int n2 = 64; //// 2^6
int *keep = malloc(sizeof(int) * (n2 - n1); ///this is to keep numbers because
/// i'll need it later in my consecutive numbers
int i = 0;
int a = 0;
n1 = 33 //// I'll start from 33 cause "bin" of 32 is "1";
while (n1 < n2) /// try to understand it now by yourself
{
t = 0;
while (t <= 3)
{
if (t == 0 || t == 2)
bin = bin + 1;
else if (t == 1)
bin = bin;
else if (t == 3)
{
bin = keep[i];
i++;
}
keep[a] = bin;
a++;
t++;
}
n1++;
}
anyway as you see I am close to solve the problem but they give me huge numbers and I must find the ones between them, unfortunately I have tried a lot of methods to calculate the "sum" using this above code and I ended up with time execution problem.
Ex: 1, 1000000000 the numbers of ones is >>> 14846928141
so can you give me a little hint what to do next, thanks in advance.
I'm doing this for CodeWar challenge: https://www.codewars.com/kata/596d34df24a04ee1e3000a25/train/c
You can solve this problem by computing the number of bits in the range 1 to n and use a simple subtraction for any subrange:
#include <stdio.h>
#include <stdlib.h>
/* compute the number of bits set in all numbers between 0 and n excluded */
unsigned long long bitpop(unsigned long long n) {
unsigned long long count = 0, p = 1;
while (p < n) {
p += p;
/* half the numbers in complete slices of p values have the n-th bit set */
count += n / p * p / 2;
if (n % p >= p / 2) {
/* all the numbers above p / 2 in the last partial slice have it */
count += n % p - p / 2;
}
}
return count;
}
int main(int argc, char *argv[]) {
unsigned long long from = 1000, to = 2000;
if (argc > 1) {
to = from = strtoull(argv[1], NULL, 0);
if (argc > 2) {
to = strtoull(argv[1], NULL, 0);
}
}
printf("bitpop from %llu to %llu: %llu\n", from, to, bitpop(to + 1) - bitpop(from));
return 0;
}
Here is a proposal for a speedup:
Find smallest y1 such that y1 >= x1 and that y1 is a power of 2
Find largest y2 such that y2 <= x2 and that y2 is a power of 2
Find p1 and p2 such that 2^p1=y1 and 2^p2=y2
Calculate the amount of 1:s between y1 and y2
Deal with x1 to y1 and y2 to x2 separately
Sum the results from 4 and 5
Let's focus on step 4. Let f(n) be the sum of ones up to (2^n)-1. We can quickly realize that f(n) = 2*f(n-1) + 2^(n-1) and that f(1)=1. This can be even further refined so that you don't have to deal with recursive calls, but I highly doubt it will be of any importance. Anyway, f(n) = n*2^(n-1)
To get the result between y1 and y2, just use f(p2)-f(p1)
For step 5, you can likely use a modified version of step 4.
EDIT:
Maybe I was to quick to say "quickly realize". Here is a way to understand it. The amounts of ones up to 2¹-1 is easy to see. The only two binary numbers below 2¹ are 0 and 1. To get the number of ones up to 2² we take the numbers below 2¹ and make a column:
0
1
Clone it:
0
1
0
1
And put 0:s before the first half and 1:s before the second half:
00
01
10
11
To get 2³ we do the same. Clone it:
00
01
10
11
00
01
10
11
And add 0 and 1:
000
001
010
011
100
101
110
111
Now it should be easy to see why f(n) = 2*f(n-1) + 2^(n-1). The cloning gives 2f(n-1) and adding the 0:s and 1:s gives 2^(n-1). If 2^(n-1) is hard to understand, remember that 2^(n-1)=(2^n)/2. In each step we have 2^n rows and half of them get an extra 1.
EDIT2:
When I looked at these columns, I got an idea for how to do step 5. Let's say that you want to find the amounts of 1:s from 10 to 15. Binary table for this would be:
10: 1010
11: 1011
12: 1100
13: 1101
14: 1110
15: 1111
Look at the interval 12-15. The last two digits in binary is a copy of the corresponding table for 0-3. That could be utilized, but I leave that to you.
EDIT 3:
This was a fun problem. I wrote some python code that does this. I get some problems with too many recursive calls, but that could be solved pretty easily, and it should not be too complicated to convert this to C:
def f(n):
return n*2**(n-1)
def numberOfOnes(x):
if(x==0):
return 0
p = floor(log(x,2))
a = f(p)
b = numberOfOnes(x-2**p)
c = x - 2**p +1
return a+b+c
I made an image so that you easier can understand what a, b and c does in the function numberOfOnes if we call it with numberOfOnes(12):
I have finally converted it to C. Of course I have used some code I found here on Stack overflow. I borrowed code for integer versions of log2 and pow, and made some small modifications.
This code is probably possible to optimize further, but it is not necessary. It is lighting fast, and I was not able to measure it's performance.
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <stdint.h>
#include <inttypes.h>
typedef uint64_t T;
// https://stackoverflow.com/a/11398748/6699433
const int tab64[64] = {
63, 0, 58, 1, 59, 47, 53, 2,
60, 39, 48, 27, 54, 33, 42, 3,
61, 51, 37, 40, 49, 18, 28, 20,
55, 30, 34, 11, 43, 14, 22, 4,
62, 57, 46, 52, 38, 26, 32, 41,
50, 36, 17, 19, 29, 10, 13, 21,
56, 45, 25, 31, 35, 16, 9, 12,
44, 24, 15, 8, 23, 7, 6, 5};
T log2_64 (T value) {
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value |= value >> 32;
return tab64[((T)((value - (value >> 1))*0x07EDD5E59A4E28C2)) >> 58];
}
// https://stackoverflow.com/a/101613/6699433
T ipow(T base, T exp) {
T result = 1;
for (;;) {
if (exp & 1) result *= base;
exp >>= 1;
if (!exp) break;
base *= base;
}
return result;
}
T f(T n) { return ipow(2,n-1)*n; }
T numberOfOnes(T x) {
if(x==0) return 0;
T p = floor(log2(x));
T a = f(p);
T e = ipow(2,p);
T b = numberOfOnes(x-e);
T c = x - e + 1;
return a+b+c;
}
void test(T u, T v) {
assert(numberOfOnes(u) == v);
}
int main() {
// Sanity checks
test(0,0);
test(1,1);
test(2,2);
test(3,4);
test(4,5);
test(5,7);
test(6,9);
// Test case provided in question
test(1000000000,14846928141);
}
int x1 = 5;
int x2 = 10;
int i=0;
int looper = 0;
unsigned long long ones_count = 0;
for(i=x1; i<=x2; i++){
looper = i;
while(looper){
if(looper & 0x01){
ones_count++;
}
looper >>= 1;
}
}
printf("ones_count is %llu\n", ones_count);
return 0;
OUTPUT: ones_count is 12
Here is a way to count every single bit for every value in between the two values. The shift/mask will be faster than your arithmetic operators most likely, but will still probably time out. You need a clever algorithm like the other answer suggests i think, but heres the stupid brute force way :)
This was my solution to the problem:
** = exponentiation
/ = whole number division
Consider the numbers from 1 to 16:
00001
00010
00011
00100
00101
00110
00111
01000
01001
01010
01011
01100
01101
01110
01111
10000
If you pay attention to each column, you'll notice a pattern. The bit at column index i (0,1,2 ...) from the right runs through a cycle of length 2**(i+1), that is every 2**(i+1) rows, the pattern in column i repeats itself. Notice also that the first cycle starts at the first occurrence of a 1 in a given column. The number of ones in a pattern is half of the patterns length.
Example:
i pattern
0 10
1 1100
2 11110000
3 1111111100000000
...
So, given the task of summing all ones up to n, we have to keep track of how many times each pattern repeats itself and also if a pattern fails to complete itself.
Solution:
Let x be the biggest exponent of a binary number n and let s be the sum of all ones up to n. Then, for i = (0, 1, 2, ... , x) add (n / 2**(i+1)*(2**i) to s. If the remainder is bigger than 2**i, add 2**i to s, else add the remainder. Then subtract 2**i from n and repeat the process.
Example:
n = 7 -> x = 2
(7 / 2**1)*(2**0) = 3
7 % 2**1 = 1 !> 2**0
s = 1 + 3 (4)
n = n - 2**0 (6)
(6 / 2**2)*(2**1) = 2
6 % 2**2 = 2 !> 2**1
s = s + 2 + 2 (8)
n = n - 2**1 (4)
(4 / 2**3)*(2**2) = 0
4 % 2**3 = 4 !> 2**2
s = s + 4 (12)
n = n - 2**2 (0)
s = 12
Maybe not the best explanation or the most beautiful solution, but it works fine.
In python:
def cnt_bin(n):
bits = n.bit_length()
s = 0
for i in range(bits):
s += (n // 2**(i+1))*2**i
if n % 2**(i+1) > 2**i:
s += 2**i
else:
s += (n % 2**(i+1))
n -= 2**i
return s
Then, for a range [a, b] you just compute cnt_bin(b) - cnt_bin(a-1)

How does this foo function works?

This C program will take the value stored in the variable a and print them one by one.
#include <stdio.h>
void foo(int n, int sum)
{
int k = 0, j = 0;
if (n == 0)
return;
k = n % 10;
j = n / 10;
sum = sum + k;
foo (j, sum);
printf ("%d, ", k);
}
int main ()
{
int a = 2048, sum = 0;
foo (a, sum);
printf("\n");
return 0;
}
Output:
2, 0, 4, 8,
When the function foo executes:
1) For the first time: n = 2048, k = 8, j = 204, sum = 8
2) For the second time: n = 204, k = 4, j = 20, sum = 12
3) For the third time: n = 20, k = 0, j = 2, sum = 12
4) For the fourth time: n = 2, k = 2, j = 0, sum = 14
If I replace the line (present in the foo function):
printf ("%d, ", k);
with this:
printf ("%d | %d, ", k, sum);
Output:
2 | 14, 0 | 12, 4 | 12, 8 | 8,
Can someone please explain how this program works:
1) How it's printing value stored in a?
2) And in this order: 2, 0, 4, 8, ?
3) Why is the value of sum is changing when we're printing values of k?
4) What would happen when n become 0?
You are calling the function foo on a.
That is the order since you are printing AFTER you are processing the rest of the number. Try moving the call to printf before the call to foo in foo and see if you get anything different.
sum is changing because you are doing sum = sum + k and passing it to all the future calls.
When n eventually becomes 0 due to repeated divisions, the last call to foo starts returning and following them all the previous calls start returning after printing the digit they had extracted using n % 10

How to choose the best marks with specified credits in c programming?

I want to make a program to get the weighted average (formula = (mark*(credits corresponds to it))/total credits) from the best(highest) 120 credits module from the following marks and credits (the credits corresponds to the module):
module[12]={48, 77, 46, 82, 85, 43, 49, 73, 65, 48, 47, 51}
credits[12]={60, 20, 20, 20, 10, 20, 10, 10, 10, 20, 20, 10}
What I have done is bubble sort the array, so that the array is sorted by decreasing manner to know which marks is higher, as shown below:
module[12]={85, 82, 77, 73, 65, 51, 49, 48, 48, 47, 46, 43}
credits[12]={10, 20, 20, 10, 10, 10, 10, 60, 20, 20, 20, 20}
And then I need to choose the best 120 credits module from the sorted array so that the weighted average will be maximum, but then I have no idea where to start. =(
Someone help me! Thanks a lot!
EDIT:
I have tried to work out the code myself, and eventually get the following code, it works, but for some special case it stop working =(
float credits=0, result=0;
n=0;
struct{
float credits;
float result;
float n;
float addpoint;
}point;
while (credits < 120){
credits+=credits[n];
result+=(result[n]*credits[n]);
n++;
}
if (credits != 120){
credits -= credits[n-1];
result -= (result[n-1]*credits[n-1]);
point.credits = credits;
point.result = result;
point.n = (n-1)-1;
point.addpoint = n;
again: while (credits < 120){
credits+=credits[n];
result+=(result[n]*credits[n]);
n++;
}
if (credits != 120){
point.credits -= credits[point.n-1];
point.result -= result[point.n-1]*credits[point.n-1];
point.n--;
credits = point.credits;
result = point.result;
n = point.addpoint-1;
goto again;
}
}
EDIT:
Solved. Using knapsack problem code/integer linear programming by the application of glpk
The other way, which is practical for small examples like the one you've got, is to use dynamic programming. One can build up a table of "optimal score if you use the first k subjects, and want credits to add up to T". The code's a bit messy because C doesn't make it particularly easy to have dynamically sized 2d arrays, but here's a solution. Probably your professor was expecting something along these lines.
A small note, I divided all the credits (and the target credits of 120) by 10 because the common factor was redundant, but the code works just fine without that (it'll just use a tad more memory and time).
#include <stdio.h>
#include <stdlib.h>
int max(int a, int b) {
return a > b ? a : b;
}
#define GET(t, i, j, n) ((t)[(i) * (n + 1) + j])
// optimize_marks takes arrays creds and marks (both of length n),
// and finds a subset I of 0..(n-1) that maximizes
// sum(i in I)creds[i]*marks[i], such that sum(i in I)creds[i] = total.
void optimize_marks(size_t n, int *creds, int *marks, int total) {
// tbl[k * (total + 1) + T] stores the optimal score using only the
// first k subjects for a total credit score of T.
// tbl[n * (total + 1) + total] will be the final result.
// A score of -1 means that the result is impossible.
int *tbl = malloc((n + 1) * (total + 1) * sizeof(int));
for (int i = 0; i <= n; i++) {
for (int T = 0; T <= total; T++) {
if (i == 0) {
// With 0 subjects, the best score is 0 if 0 credits are
// required. If more than 0 credits are required, the result
// is impossible.
GET(tbl, i, T, total) = -(T > 0);
continue;
}
// One way to get T credits with the first i subjects is to
// get T credits with the first (i-1) subjects.
GET(tbl, i, T, total) = GET(tbl, i - 1, T, total);
// The other way is to use the marks for the i'th subject
// and get the rest of the credits with the first (i-1) subjects.
// We have to check that it's possible to use the first (i-1) subjects
// to get the remainder of the credits.
if (T >= creds[i-1] && GET(tbl, i - 1, T - creds[i-1], total) >= 0) {
// Pick the best of using and not using the i'th subject.
GET(tbl, i, T, total) = max(
GET(tbl, i, T, total),
GET(tbl, i - 1, T - creds[i-1], total) + marks[i-1] * creds[i-1]);
}
}
}
int T = total;
for (int i = n; i > 0; i--) {
if (GET(tbl, i - 1, T, total) < GET(tbl, i, T, total)) {
printf("%d %d %d\n", i, creds[i-1], marks[i-1]);
T -= creds[i-1];
}
}
}
int main(int argc, char *argv[]) {
int creds[] = {6, 2, 2, 2, 1, 2, 1, 1, 1, 2, 2, 1};
int marks[] = {48, 77, 46, 82, 85, 43, 49, 73, 65, 48, 47, 51};
optimize_marks(12, creds, marks, 12);
return 0;
}
The program gives the solution as the ILP program:
12 1 51
11 2 47
10 2 48
9 1 65
8 1 73
5 1 85
4 2 82
2 2 77
This is an integer linear programming problem. You want to find a vector [x1 x2 x3 ... x12] where each of the x's is either 0 or 1, such that sum(x[i] * cred[i]) = 120 and that sum(x[i] * cred[i] * marks[i]) is maximised.
There's a large body of research in how to solve such problems, but there's existing solvers out there and ready for you to use and using them is going to save you a vast amount of time over coding a solver up yourself.
Here's a module file for glpk, a free linear programming and integer linear programming solver. You can run it by installing glpk, saving this to a file then running glpsol -m <filename>
set I := 1..12;
var x{I} binary;
param cred{I};
param marks{I};
maximize s:
sum{i in I}(x[i] * cred[i] * marks[i]);
s.t. totalcreds: sum{i in I}(x[i] * cred[i]) = 120;
solve;
printf {i in I} "%d: %d %d %d\n", i, x[i], cred[i], marks[i];
data;
param cred := 1 60, 2 20, 3 20, 4 20, 5 10, 6 20, 7 10, 8 10, 9 10, 10 20, 11 20, 12 10;
param marks := 1 48, 2 77, 3 46, 4 82, 5 85, 6 43, 7 49, 8 73, 9 65, 10 48, 11 47, 12 51;
end;
The output is this:
1: 0 60 48
2: 1 20 77
3: 0 20 46
4: 1 20 82
5: 1 10 85
6: 0 20 43
7: 0 10 49
8: 1 10 73
9: 1 10 65
10: 1 20 48
11: 1 20 47
12: 1 10 51
That is, you should pick courses 2, 4, 5, 8, 9, 10, 11, 12 (ie: the courses with a '1' by them).
You should probably start by isolating all the combinaisons of credits[] elements whose sum equals 120 and store them before calculating all the means.
It would look like that :
// test for all possible combinaisons :
// [0] + [1] + [2]..., [1] + [0] + [2]...
// starting point on the array : n
while(n < 12){
// if the sum isnt equal to 120 and
// we havent covered all the array yet
if(temp < 120 && i < 12){
// if i is different from the starting point
if(i < 11 && i != n){
i++;
temp += credits[i];
// store i
}
}
if(temp >120 && i < 11){
temp -= credits[i];
// remove i
i++;
}
if(temp == 120){
// starting point ++
n++;
}
}
It's not optimal, but it could work.

Resources