Gå til innhold

C#: Problem 22 på projecteuler: ser noen feilen i koden?


Anbefalte innlegg

Hei!

har et problem jeg virkelig ikke klarer å løse - jeg har en feil i koden et sted, men jeg aner ikke hva det kan være. Oppgaven det gjelder er temmelig simpel:

 

Using names.txt (right click and 'Save Link/Target As...'), a 46K text file containing over five-thousand first names, begin by sorting it into alphabetical order. Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list to obtain a name score.

 

For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, COLIN would obtain a score of 938 53 = 49714.

 

What is the total of all the name scores in the file?

using System;

class MainClass
{
 private static string[] names = new string[] {"ELDEN","DORSEY","DARELL","BRODERICK","ALONSO"};

 static void Main()
 {
	  Array.Sort(names);
	  Console.WriteLine("Sum is " + SumNames());
 }

 static uint SumNames()
 {
	  uint total_sum = 0;
	  for(int i = 0; i < names.Length; i++) {
		   int char_sum = getNameValue(names[i]);
		   total_sum += (uint)(char_sum * (i + 1));
	  }
	  return total_sum;
 }

 static int getNameValue(string name)
 {
	  char[] chars = name.ToCharArray();
	  int char_sum = 0;
	  for(int c = 0; c < chars.Length; c++) {
		   char_sum += (int)chars[c] - 64;
	  } 
	  return char_sum;
 }
}

arrayet er kortet ned her, egentlig er det over 5000 navn i det. Koden er så simpel at det er vanskelig å skjønne hvor det kan være en feil hen. det eneste jeg fant ut, er at COLIN skal være nr. 938 i lista, men i mitt array er det nr. 937. og ja, jeg har husket at array starter å telle med null, så det er ikke der den feilen ligger.

 

Noen som ser noe jeg ikke ser?

Lenke til kommentar
Videoannonse
Annonse

Kan det være noe sorteringstull? Hva slags culture bruker den når den sorterer? Det kan være noe AA som havner bakerst, dermed rykker COLIN ett hakk fram.

 

EDIT: jeg har ikke tilgang til euler-koden min herfra, men jeg kan sjekke hva som er første og siste element i den sorterte lista i min løsning i kveld hvis du vil.

Endret av steingrim
Lenke til kommentar

Sliter med oppgaven selv!

 

Men hos meg blir Colin regnet ut riktig (49714), da jeg har tatt høyde for AA-feilen. Men det blir feil svar for det...

 

Svaret jeg kommer fram til, som er feil, er 871197733.

 

Noen tips Hockey500?

 

 

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Solution022
{
   /*
    * Using names.txt, a 46K text file containing over five-thousand first names, 
    * begin by sorting it into alphabetical order. Then working 
    * out the alphabetical value for each name, multiply this value 
    * by its alphabetical position in the list to obtain a name score.
    * 
    * For example, when the list is sorted into alphabetical order, COLIN, 
    * which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. 
    * So, COLIN would obtain a score of 938 * 53 = 49714.
    * 
    * What is the total of all the name scores in the file?
    */

   class Solution22
   {
       static void Main(string[] args)
       {
           DateTime startTime = DateTime.Now;

           string[] names = getAndSortNames();
           double sum = 0;

           for (int i = 0; i < names.Length - 1; i++)
           {
               sum += (double)calculateScore(names[i], i + 2);  
           }

           sum += (double)calculateScore(names[names.Length - 1], 1); //Compansate for "AA" sort error

           Console.WriteLine("The sum of scores is " + sum + ".");

           TimeSpan duration = DateTime.Now - startTime;
           Console.WriteLine("Execution time: " + duration.Milliseconds + " milliseconds.\n");
       }

       public static string[] getAndSortNames()
       {
           char[] splitter = new char[1] { ',' };

           string[] names = null;
           try
           {
               // Create an instance of StreamReader to read from a file.
               // The using statement also closes the StreamReader.
               using (StreamReader sr = new StreamReader("names.txt"))
               {
                   StringBuilder line = new StringBuilder();
                   line.Append(sr.ReadLine());
                   line.Replace("\"", "");
                   names = line.ToString().Split(splitter);
                   Array.Sort(names);
               }
           }
           catch (Exception e)
           {
               Console.WriteLine("The file \"names.txt\" could not be read:");
               Console.WriteLine(e.Message);
           }
           return names;
       }

       public static double calculateScore(string name, int pos)
       {
           double score = 0;

           char[] nameArray = name.ToCharArray();

           for (int i = 0; i < nameArray.Length; i++)
           {
               score += nameArray[i] - 64;
           }

           return (score * pos);
       }
   }
}

Lenke til kommentar

Anvend en kulturnøytral sammenlikningsklasse når du kaller Sort-metoden:

Array.Sort(names, StringComparer.InvariantCulture);

Da slipper du å måtte kompensere for sorteringsfeilen, og løsningskoden blir en tanke mer oversiktelig samt interkompatibel med andre kulturinnstillinger. Selv brukte jeg LINQ til å løse denne oppgaven (opprinnelig i VB. net, riktignok):

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

// Needs reference to Microsoft.VisualBasic (Project -> Add Reference)
using Microsoft.VisualBasic.FileIO;

namespace Problem22
{
class Solution
{

	static void Main(string[] args)
	{

		/*
		* Using names.txt (right click and 'Save Link/Target As...'), a 46K text file containing over five-thousand first 
		* names, begin by sorting it into alphabetical order. Then working out the alphabetical value for each name, 
		* multiply this value by its alphabetical position in the list to obtain a name score.
		*
		* For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, 
		* is the 938th name in the list. So, COLIN would obtain a score of 938 53 = 49714.
		*
		* What is the total of all the name scores in the file?
		*/

		long i = 1; // Counter

		try
		{

			// I'm aware of the objections, but I doubt Microsoft.VisualBasic will be deprecated anytime soon.
			using (TextFieldParser Reader = new TextFieldParser("C:\\names.txt"))
			{
				Reader.TextFieldType = FieldType.Delimited;
				Reader.Delimiters = new string[] { "," };
				Reader.HasFieldsEnclosedInQuotes = true;

				// Sort and accumulate
				var OrderedNames = Reader.ReadFields().OrderBy(a => a, StringComparer.InvariantCulture);
				var TotalScore = OrderedNames.Select(x => CharSum(x, 64) * i++).Sum();

				// Output result (871198282)
				Console.WriteLine("Solution: {0}", TotalScore);
			}
		}

		catch (Exception ex)
		{
			Console.WriteLine(ex.Message);
		}

		// Pause()
		Console.ReadKey();

	}

	static long CharSum(string Text, long Offset)
	{
		// Convert each character to its ASCII-representation, subtract by offset and return sum
		return Text.ToCharArray().Cast<long>().Select(x => x - Offset).Sum();
	}

}
}

 

Endret av aadnk
Lenke til kommentar
Anvend en kulturnøytral sammenlikningsklasse når du kaller Sort-metoden:

Array.Sort(names, StringComparer.InvariantCulture);

Da slipper du å måtte kompensere for sorteringsfeilen, og løsningskoden blir en tanke mer oversiktelig samt interkompatibel med andre kulturinnstillinger. Selv brukte jeg LINQ til å løse denne oppgaven (opprinnelig i VB. net, riktignok):

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

// Needs reference to Microsoft.VisualBasic (Project -> Add Reference)
using Microsoft.VisualBasic.FileIO;

namespace Problem22
{
class Solution
{

	static void Main(string[] args)
	{

		/*
		* Using names.txt (right click and 'Save Link/Target As...'), a 46K text file containing over five-thousand first 
		* names, begin by sorting it into alphabetical order. Then working out the alphabetical value for each name, 
		* multiply this value by its alphabetical position in the list to obtain a name score.
		*
		* For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, 
		* is the 938th name in the list. So, COLIN would obtain a score of 938 53 = 49714.
		*
		* What is the total of all the name scores in the file?
		*/

		long i = 1; // Counter

		try
		{

			// I'm aware of the objections, but I doubt Microsoft.VisualBasic will be deprecated anytime soon.
			using (TextFieldParser Reader = new TextFieldParser("C:\\names.txt"))
			{
				Reader.TextFieldType = FieldType.Delimited;
				Reader.Delimiters = new string[] { "," };
				Reader.HasFieldsEnclosedInQuotes = true;

				// Sort and accumulate
				var OrderedNames = Reader.ReadFields().OrderBy(a => a, StringComparer.InvariantCulture);
				var TotalScore = OrderedNames.Select(x => CharSum(x, 64) * i++).Sum();

				// Output result (871198282)
				Console.WriteLine("Solution: {0}", TotalScore);
			}
		}

		catch (Exception ex)
		{
			Console.WriteLine(ex.Message);
		}

		// Pause()
		Console.ReadKey();

	}

	static long CharSum(string Text, long Offset)
	{
		// Convert each character to its ASCII-representation, subtract by offset and return sum
		return Text.ToCharArray().Cast<long>().Select(x => x - Offset).Sum();
	}

}
}

Ahhh.... Det hjalp gitt. Nå sorterer den riktig og gir rett svar. Takk for tips!

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...