I have a question about my console program.
It has to count using Horner algorithm. There is no exception thrown, however, it does not give the right results.
If anyone could help me I would be very grateful, because I do not know what to do ...
Here is the code of my program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Consola_Horner_Rekurencyjnie
{
class Program
{
static void Main(string[] args)
{
int n;
Console.WriteLine("Podaj stopień wielomioanu: ");
n = Convert.ToInt32(Console.ReadLine());
int[] a = new int[++n];
Console.WriteLine("Podaj wartosc a: ");
for (int i = 0; i < n; i++)
{
Console.WriteLine("a [" + i + "] = ");
a[i] = Convert.ToInt32(Console.ReadLine());
}
int x;
Console.WriteLine("Podaj x:");
x = Convert.ToInt32(Console.ReadLine());
int Horner;
Horner = a[0];
for (int i = 1; i < n; i++)
{
Horner = Horner * (i - 1) * x + a[i];
}
Console.WriteLine("Wynik to:" + Horner);
Console.ReadLine();
}
}
}
This is the second option calculates the code, but the counts are all wrong:
Func<int, int> Horner = null;
Horner = (i) => (i == 0) ? a[0] : Horner(i - 1) * x + a[i];
Console.WriteLine("Wynik to:" + Horner(x));
Console.ReadLine();
I wanted to rewrite the original code from C + + (in the form of a recursive algorithm).
The original code looks like:
int Horner;
int n;
int *a = new int[n];
int x;
int main()
{
cout <<"Podaj stopień wielomianu: ";
cin >> n;
cin.ignore();
cout << "Podaj wartość a: \n";
for (int i = 0; i <= n; i++)
{
cout <<"a[" <<i<<"] = ";
cin >> a[i];
cin.ignore();
}
cout <<"Podaj x: ";
cin >> x;
cin.ignore();
cout <<"Wynik to: " << Horner(n);
getchar ();
return 0;
}
int Horner (int i)
{
if (i == 0)
return a[0];
else
return Horner (i - 1) * x + a[i];
}
Already I do not know how to do it ... Wandering still in the same place ...
You're unnecesarily multiplying by (i-1) in your loop.
Change it to:
int Horner;
Horner = a[0];
for (int i = 1; i < n; i++)
{
Horner = Horner * x + a[i];
}
or even better to:
int Horner = 0;
foreach (int wspolczynnik in a)
{
Horner = Horner * x + wspolczynnik;
}
You probably saw some implementation that had Horner(i-1) * x + a(i), but the (i-1) is an array index in this case, not a multiplier.
edit:
On the other hand your recursive version takes one parameter - the degree of the polynomial, and you tried to call it with x. Do it with n!
int result = Horner(n);
IMO it would be much clearer if it took 2 parameters - degree of the polynomial, and x:
Func<int, int, int> Horner = null;
Horner = (i, x) => (i == 0) ? a[0] : Horner(i - 1, x) * x + a[i];
int result = Horner(n, x);
I found here "good" source code in c# for Horner scheme:
private IEnumerable<int> getDivisors(int n)
{
if (n == 0)
return (IEnumerable<int>)new int[] { 0 };
else
return Enumerable.Range(-Math.Abs(n), 2 * Math.Abs(n) + 1)
.Where(a => a != 0)
.Where(a => (n % a) == 0);
}
private bool findRootWithHornerScheme(int[] coefficientsA, int x, out int[] coefficientsB)
{
var lenght = coefficientsA.Length;
var tmpB = new int[lenght];
coefficientsB = new int[lenght - 1];
tmpB[0] = coefficientsA[0];
for (int i = 1; i < lenght; i++)
{
tmpB[i] = tmpB[i - 1] * x + coefficientsA[i];
}
//ak je posledny koefiecient B == 0 ,tak zadane x je korenom polynomu
if (tmpB[lenght - 1] == 0)
{
Array.Copy(tmpB, coefficientsB, lenght - 1);
return true;//bol najdeny koren
}
//nebol najdeny koren a metoda vrati false
return false;
}
Related
so i have this function:
static int[] AddArrays(int[] a, int[] b)
{
int length1 = a.Length;
int length2 = b.Length;
int carry = 0;
int max_length = Math.Max(length1, length2) + 1;
int[] minimum_arr = new int[max_length - length1].Concat(a).ToArray();
int[] maximum_arr = new int[max_length - length2].Concat(b).ToArray();
int[] new_arr = new int[max_length];
for (int i = max_length - 1; i >= 0; i--)
{
int first_digit = maximum_arr[i];
int second_digit = i - (max_length - minimum_arr.Length) >= 0 ? minimum_arr[i - (max_length - minimum_arr.Length)] : 0;
if (second_digit + first_digit + carry > 9)
{
new_arr[i] = (second_digit + first_digit + carry) % 10;
carry = 1;
}
else
{
new_arr[i] = second_digit + first_digit + carry;
carry = 0;
}
}
if (carry == 1)
{
int[] result = new int[max_length + 1];
result[0] = 1;
Array.Copy(new_arr, 0, result, 1, max_length);
return result;
}
else
{
return new_arr;
}
}
it basically takes 2 lists of digits and adds them together. the point of this is that each array of digits represent a number that is bigger then the integer limits. now this function is close to working the results get innacurate at certein places and i honestly have no idea why. for example if the function is given these inputs:
"1481298410984109284109481491284901249018490849081048914820948019" and
"3475893498573573849739857349873498739487598" (both of these are being turned into a array of integers before being sent to the function)
the expected output is:
1,481,298,410,984,109,284,112,957,384,783,474,822,868,230,706,430,922,413,560,435,617
and what i get is:
1,481,298,410,984,109,284,457,070,841,142,258,634,158,894,233,092,241,356,043,561,7
i would very much appreciate some help with this ive been trying to figure it out for hours and i cant seem to get it to work perfectly.
I suggest Reverse arrays a and b and use good old school algorithm:
static int[] AddArrays(int[] a, int[] b) {
Array.Reverse(a);
Array.Reverse(b);
int[] result = new int[Math.Max(a.Length, b.Length) + 1];
int carry = 0;
int value = 0;
for (int i = 0; i < Math.Max(a.Length, b.Length); ++i) {
value = (i < a.Length ? a[i] : 0) + (i < b.Length ? b[i] : 0) + carry;
result[i] = value % 10;
carry = value / 10;
}
if (carry > 0)
result[result.Length - 1] = carry;
else
Array.Resize(ref result, result.Length - 1);
// Let's restore a and b
Array.Reverse(a);
Array.Reverse(b);
Array.Reverse(result);
return result;
}
Demo:
string a = "1481298410984109284109481491284901249018490849081048914820948019";
string b = "3475893498573573849739857349873498739487598";
string c = string.Concat(AddArrays(
a.Select(d => d - '0').ToArray(),
b.Select(d => d - '0').ToArray()));
Console.Write(c);
Output:
1481298410984109284112957384783474822868230706430922413560435617
So the problem that I'm trying to optimize is to find and print all four-digit numbers of the type ABCD for which: A + B = C + D.
For example:
1001
1010
1102
etc.
I have used four for loops to solve this (one for every digit of the number).
for (int a = 1; a <= 9; a++)
{
for (int b = 0; b <= 9; b++)
{
for (int c = 0; c <= 9; c++)
{
for (int d = 0; d <= 9; d++)
{
if ((a + b) == (c + d))
{
Console.WriteLine(" " + a + " " + b + " " + c + " " + d);
}
}
}
}
}
My question is: how can I solve this using only 3 for loops?
Here's an option with two loops (though still 10,000 iterations), separating the pairs of digits:
int sumDigits(int input)
{
int result = 0;
while (input != 0)
{
result += input % 10;
input /= 10;
}
return result;
}
//optimized for max of two digits
int sumDigitsAlt(int input)
{
return (input % 10) + ( (input / 10) % 10);
}
// a and b
for (int i = 0; i <= 99; i++)
{
int sum = sumDigits(i);
// c and d
for (int j = 0; j <= 99; j++)
{
if (sum == sumDigits(j))
{
Console.WriteLine( (100 * i) + j);
}
}
}
I suppose the while() loop inside of sumDigits() might count as a third loop, but since we know we have at most two digits we could remove it if needed.
And, of course, we can use a similar tactic to do this with one loop which counts from 0 to 9999, and even that we can hide:
var numbers = Enumerable.Range(0, 10000).
Where(n => {
// there is no a/b
if (n < 100 && n == 0) return true;
if (n < 100) return false;
int sumCD = n % 10;
n /= 10;
sumCD += n % 10;
n /= 10;
int sumAB = n % 10;
n /= 10;
sumAB += n % 10;
return (sumAB == sumCD);
});
One approach is to write a method that takes in an integer and returns true if the integer is four digits and the sum of the first two equal the sum of the second two:
public static bool FirstTwoEqualLastTwo(int input)
{
if (input < 1000 || input > 9999) return false;
var first = input / 1000;
var second = (input - first * 1000) / 100;
var third = (input - first * 1000 - second * 100) / 10;
var fourth = input - first * 1000 - second * 100 - third * 10;
return (first + second) == (third + fourth);
}
Then you can write a single loop from 1000-9999 and output the numbers for which this is true with a space between each digit (not sure why that's the output, but it appears that's what you were doing in your sample code):
static void Main(string[] args)
{
for (int i = 1000; i < 10000; i++)
{
if (FirstTwoEqualLastTwo(i))
{
Console.WriteLine(" " + string.Join(" ", i.ToString().ToArray()));
}
}
Console.Write("Done. Press any key to exit...");
Console.ReadKey();
}
We can compute the value of d from the values of a,b,c.
for (int a = 1; a <= 9; a++)
{
for (int b = 0; b <= 9; b++)
{
for (int c = 0; c <= 9; c++)
{
if (a + b >= c && a + b <= 9 + c)
{
int d = a + b - c;
Console.WriteLine(" " + a + " " + b + " " + c + " " + d);
}
}
}
}
We can further optimize by changing the condition of the third loop to for (int c = max(0, a + b - 9); c <= a + b; c++) and getting rid of the if statement.
can you help me to create a logic for magic square metric. In given example, I have created a code for generate Magic Square for odd numbers like 3x3, 5x5, 7x7 metric and double even numbers like 4×4 , 8×8 but unable to found a proper solution for create single even value magic square metric like 6x6, 10x10 etc.
In current implementation anyone can enter a number (n) in input and it will create a nxn magic square metric. But not working fine with single even numbers
class Program
{
public static void Main(string [] args )
{
Console.WriteLine("Please enter a number:");
int n1 = int.Parse(Console.ReadLine());
// int[,] matrix = new int[n1, n1];
if (n1 <= 0)
{
Negativ();
}
else if (n1 == 2)
{
Zwei();
}
else if ((n1 != 2) && !(n1 < 0) && (n1 % 2 != 0))
{
Odd (n1 );
}
else if ((n1 != 2) && !(n1 < 0) && ((n1 - 2) % 4 == 0))
{//singl Even
SingleEven(n1);
}
else if ((n1 != 2) && !(n1 < 0) && (n1 % 4 == 0))
{
DoubleEven (n1);
}
}
private static void Negativ(){
Console.WriteLine("Sorry, the number must be positive and greater than 3 ");
Console.ReadLine();
}
public static void Zwei(){
Console.WriteLine("Sorry,there is no magic square of 2x2 and the number must be and greater than 3 ");
Console.ReadLine();
}
public static void Odd ( int n)// odd method
{
int[,] magicSquareOdd = new int[n, n];
int i;
int j;
// Initialize position for 1
i = n / 2;
j = n - 1;
// One by one put all values in magic square
for (int num = 1; num <= n * n; )
{
if (i == -1 && j == n) //3rd condition
{
j = n - 2;
i = 0;
}
else
{
//1st condition helper if next number
// goes to out of square's right side
if (j == n)
j = 0;
//1st condition helper if next number is
// goes to out of square's upper side
if (i < 0)
i = n - 1;
}
//2nd condition
if (magicSquareOdd[i, j] != 0)
{
j -= 2;
i++;
continue;
}
else
{
//set number
magicSquareOdd[i, j] = num++;
//1st condition
j++; i--;
}
}
// print magic square
Console.WriteLine("The Magic Square for " + n + " is : ");
Console.ReadLine();
for ( i = 0; i < n; i++)
{
for ( j = 0; j < n; j++)
Console.Write(" " + magicSquareOdd[i, j] + " ");
Console.WriteLine();
Console.ReadLine();
}
Console.WriteLine(" The sum of each row or column is : " + n * (n * n + 1) / 2 + "");
Console.ReadLine();
}
public static void SingleEven(int n )
{
// int n = magic .Length ;
int[,] magicSquareSingleEven = new int[n, n];
int halfN = n / 2;
int k = (n - 2) / 4;
int temp;
int[] swapcol = new int[n];
int index = 0;
int[,] minimagic = new int[halfN, halfN];
*Odd(minimagic) ;* // here is the problem
for (int i = 0; i < halfN; i++)
for (int j = 0; j < halfN; j++)
{
magicSquareSingleEven[i, j] = minimagic[i, j];
magicSquareSingleEven[i+ halfN , j+halfN ] = minimagic[i, j]+ halfN *halfN ;
magicSquareSingleEven[i, j + halfN] = minimagic[i, j] +2* halfN * halfN;
magicSquareSingleEven[i + halfN, j] = minimagic[i, j] +3* halfN * halfN;
}
for (int i =1; i< k ;i ++)
swapcol [index ++]=i ;
for (int i = n-k+2; i <= n ; i++)
swapcol[index++] = i;
for (int i =1; i<=halfN ;i ++)
for (int j = 1; j<= index ; j ++)
{
temp = magicSquareSingleEven[i - 1, swapcol[j - 1] - 1];
magicSquareSingleEven[i-1,swapcol[j-1]-1]=magicSquareSingleEven[i +halfN-1,swapcol[j-1]-1];
magicSquareSingleEven[i+halfN-1,swapcol[j-1]-1]=temp;
}
//swaping noses
temp=magicSquareSingleEven[k,0];
magicSquareSingleEven[k,0]=magicSquareSingleEven[k+halfN,0];
magicSquareSingleEven[k+halfN,0]=temp;
temp=magicSquareSingleEven[k+halfN,k];
magicSquareSingleEven[k+halfN,k]=magicSquareSingleEven[k,k];
magicSquareSingleEven[k,k]=temp;}
//end of swaping
// print magic square
Console.WriteLine("The Magic Square for " + n + " is : ");
Console.ReadLine();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
Console.Write(" " + magicSquareSingleEven[i, j] + " ");
Console.WriteLine();
Console.ReadLine();
}
Console.WriteLine(" The sum of each row or column is : " + n * (n * n + 1) / 2 + "");
Console.ReadLine();
}
It take pretty long time to complete the limit(n) of 100,000.
I suspect that the problem is with the CalculateAmicable() where the number get bigger and it take more time to calculate. What can I change to make it speed up faster than this?
public static void Main (string[] args)
{
CheckAmicable (1, 100000);
}
public static int CheckAmicable(int start, int end)
{
for (int i = start; i < end; i++) {
int main = CalculateAmicable (i); //220
int temp = CalculateAmicable (main); //284
int compare = CalculateAmicable (temp); //220
if (compare == main) {
if (main != temp && temp == i) {
Console.WriteLine (main + " = " + temp + " = " + compare + " i: " + i);
i = compare + 1;
}
}
}
return 0;
}
public static int CalculateAmicable(int number)
{
int total = 0;
for (int i = 1; i < number; i++) {
if (number%i == 0){
total += i;
}
}
return total;
}
Note: English is not my first language!
Yes, CalculateAmicable is inefficient - O(N) complexity - and so you have fo N tests 1e5 * 1e5 == 1e10 - ten billions operations which is slow.
The scheme which reduces complexity to O(log(N)) is
int n = 100000;
//TODO: implement IList<int> GetPrimesUpTo(int) yourself
var primes = GetPrimesUpTo((int)(Math.Sqrt(n + 1) + 1));
// Key - number itself, Value - divisors' sum
var direct = Enumerable
.Range(1, n)
.AsParallel()
.ToDictionary(index => index,
index => GetDivisorsSum(index, primes) - index);
var result = Enumerable
.Range(1, n)
.Where(x => x < direct[x] &&
direct.ContainsKey((int) direct[x]) &&
direct[(int) direct[x]] == x)
.Select(x => $"{x,5}, {direct[x],5}");
Console.Write(string.Join(Environment.NewLine, result));
The outcome is within a second (Core i7 3.2Ghz .Net 4.6 IA-64):
220, 284
1184, 1210
2620, 2924
5020, 5564
6232, 6368
10744, 10856
12285, 14595
17296, 18416
63020, 76084
66928, 66992
67095, 71145
69615, 87633
79750, 88730
Details GetDivisorsSum:
private static long GetDivisorsSum(long value, IList<int> primes) {
HashSet<long> hs = new HashSet<long>();
IList<long> divisors = GetPrimeDivisors(value, primes);
ulong n = (ulong) 1;
n = n << divisors.Count;
long result = 1;
for (ulong i = 1; i < n; ++i) {
ulong v = i;
long p = 1;
for (int j = 0; j < divisors.Count; ++j) {
if ((v % 2) != 0)
p *= divisors[j];
v = v / 2;
}
if (hs.Contains(p))
continue;
result += p;
hs.Add(p);
}
return result;
}
And GetPrimeDivisors:
private static IList<long> GetPrimeDivisors(long value, IList<int> primes) {
List<long> results = new List<long>();
int v = 0;
long threshould = (long) (Math.Sqrt(value) + 1);
for (int i = 0; i < primes.Count; ++i) {
v = primes[i];
if (v > threshould)
break;
if ((value % v) != 0)
continue;
while ((value % v) == 0) {
value = value / v;
results.Add(v);
}
threshould = (long) (Math.Sqrt(value) + 1);
}
if (value > 1)
results.Add(value);
return results;
}
The numbers are stored in the arrays with their digits in reverse order. Here is a functions that should add two numbers, a and b, and store the sum in result:
public static void SumDigitArraysDifferentSize(int[] a, int[] b, int[] result)
{
int length = Math.Max(a.Length, b.Length);
for (int i = 0; i < length; i++)
{
int lhs = (i < a.Length) ? a[i] : 0;
int rhs = (i < b.Length) ? b[i] : 0;
result[i] = (result[i] + lhs + rhs) % 10;
int carry = (result[i] + lhs + rhs) / 10;
for (int j = 1; carry > 0; j++)
{
result[i + j] = (result[i + j] + carry) % 10;
carry = (result[i + j] + carry) / 10;
}
}
}
However, if I add for example:
static void Main(string[] args)
{
int[] lhs = { 9 }
int[] rhs = { 9, 9 };
int size = Math.Max(lhs.Length, rhs.Length) + 1;
int[] result = new int[size];
SumDigitArraysDifferentSize(lhs, rhs, result);
PrintArray(result);
}
the result is:
{ 8, 1, 1 }
instead of the expected:
{ 8, 0, 1 }
What am I doing wrong?
For the MCVE:
public static void PrintArray(int[] Array)
{
Console.Write("{");
int length = Array.Length;
for (int i = 0; i < length; i++)
{
Console.Write(Array[i]);
if (i < length - 1)
{
Console.Write(", ");
}
}
Console.Write("}\n");
}
You are assigning result[i], and using the result again in the calculation of the carry.
This:
result[i] = (result[i] + lhs + rhs) % 10;
int carry = (result[i] + lhs + rhs) / 10;
Should be:
var sum = result[i] + lhs + rhs;
result[i] = (sum) % 10;
int carry = (sum) / 10;
And the same for the calculation in the for (int j = 1; ...).
For the sake of completeness, here is the result of the proposed (by #Lasse V. Karlsen) implementation from the comment section
public static void SumDigitArrays(int[] a, int[] b, int[] result)
{
int length = Math.Max(a.Length, b.Length);
for (int i = 0; i < length; i++)
{
int lhs = (i < a.Length) ? a[i] : 0;
int rhs = (i < b.Length) ? b[i] : 0;
int sum = result[i] + lhs + rhs;
result[i] = sum % 10;
int carry = sum / 10;
result[i + 1] = result[i + 1] + carry;
}
}