• 1
  • 2
2009-05-08, 03:06
  #1
Medlem
virre_01s avatar
Jag sitter här med en läxa som jag har riktigt svårt att klura ut. Det är framförallt logiken som är problemet men jag kanske kommer behöva hjälp med kodningen också. Tack på förhand

Uppgiften (är bifogad i sin helhet längre ner) är att räkna ut antalet möjliga tal som kan ha kommit från en miniräknare som saknar display. Jag måste använda mig av Lists, som jag inte har en aning om hur vanliga dom är i Sverige (En List är en serie av nodes som är sammankopplade på såvis att den föregående pekar på nästa och den i sin tur pekar på nästa osv. Jag bifogar hela List classen längre ner)

Vad jag har gjort hitilst:

Kod:
import sdsu.io*;
public class 
HW7
{

        public static List[] list = new List[
23];

        
int x Console.readLine("Input X's milliamps");
        
int y Console.readLine("Input Y's milliamps");
        
int z Console.readLine("inout Z's milliamps");

        
5;
        
5;
        
5;







Här är definitionen av nodes och även List(Sorry för texten mitt i):

Kod:
// List.java


class Node
{

   public 
Object data;
   public 
Node next;

   public 
Node()
   {
      
this.data null;
      
this.next null;
   }

   public 
Node(Object a)
   {
      
this.data a;
      
this.next null;
   }

   public 
Node(Object aNode b)
   {
      
this.data a;
      
this.next b;
   }

}  
//end Node class





public class List
{


   private 
Node head;
   private 
Node tail;



   public List()
   {
      
this.head null;
      
this.tail null;
   }


//-------------------------


   
public void insertAtFront(Object obj)
   {

      if (
this.size()==0)
      {
         
Node n = new Node(obj);
         
this.head n;
         
this.tail n;
        
      }
      else
      {
         
Node n = new Node(obj);
         
n.next this.head;
         
this.head n;
         
      }

   }


//----------------------------


   
public void insertAtBack(Object obj)
   {

      if (
this.size()==0)
      {
         
Node n = new Node(obj);
         
this.head n;
         
this.tail n;
      }
      else
      {
         
Node n = new Node(obj);
         
this.tail.next n;
         
this.tail n;
      }

   }


//------------------------------


   
public Object removeFromFront()
   {

      if (
this.size()==0)
      {
         
System.out.println("No data to remove.");
         return 
null;
      }
      else if (
this.size()==1)
      {
         
Object a this.head.data;
         
this.head null;
         
this.tail null;
         return 
a;
      }
      else
      {
         
Object a this.head.data;
         
this.head this.head.next;
         return 
a;
      }

   }


//-----------------------------


   
public Object removeFromBack()
   {

      if (
this.size()==0)
      {
         
System.out.println("No data to remove.");
         return 
null;
      }
      else if (
this.size()==1)
      {
         
Object a this.tail.data;
         
this.head null;
         
this.tail null;
         return 
a;
      }
      else
      {

         
Object a this.tail.data;


         
Node ntlnode this.head;
         while (
ntlnode.next != this.tail)
         {
            
ntlnode ntlnode.next;
         }

         
this.tail ntlnode;
         
this.tail.next null;

         return 
a;

      }

   }


//-------------------------


   
public boolean isEmpty()
   {
      return  
this.head == null;
      
//or:  return  this.size()==0;
   
}

   public 
void print()
   {
  

      if (
this.size()==0)
      {
         
System.out.println("Empty list!");
         return;
      }

      
Node curr this.head;   //start at the front of the list.
      
while (curr != null)
      {
         
System.out.println(curr.data.toString());   //print current data item.
         
curr curr.next;   //move forward to the next data item.
      
}

      
System.out.println();

   }


//-------------------------


   
public int size()
   {

      
int count 0;

      
//the WHILE loop will "roller coaster" through ALL nodes in the list,
      //counting each one.  size() will work correctly even for an empty list.

      
Node curr this.head;   //start at the front of the list.
      
while (curr != null)
      {
         
count++;   //count current data item.
         
curr curr.next;   //move forward to the next data item.
      
}

      return 
count;

   }


//-------------------------


}  //end List class 


Och här är själva uppgiften:

HW#7 SPECS
==========


In your HW7 program code, you must use ONLY Linked List data structures,
i.e. use the List.java file from the online lecture notes.
You must NOT use non-List data structures (e.g., arrays, etc).
(Unless, they are only used to store Lists, such as described in the
"Extra Hint" below.)


Speed requirements:
Your program must compute and output the answer in less than 5 seconds (on rohan).



HINT:
Don't compute and check all possible combinations after the
user has inputted his or her data. There are over 31 billion combinations,
so examining them individually will result in large running times.
Instead, you can decrease your program's running time by figuring out
clever ways to decrease the number of combinations you must examine.
E.g., you can speed up your program's running time by pre-computing and storing
relevant information ahead of time (in List data structures).


SAMPLE RUN:

rohan% javac HW7.java
rohan% java HW7

Input X's milliamps: <--- assume user enters 30
Input Y's milliamps: <--- assume user enters 65
Input Z's milliamps: <--- assume user enters 65

Possible solutions = 819


---------------------------------------------------------------------------


EXTRA HINT
==========

One way, to tackle HW7:

Create an array which contains 23 List objects, i.e. lists[0] to lists[22].
Check all the integers from -999 to 999.
For each of those integers, compute the number of calculator "segments", k,
required for it.
Insert at the back of lists[k], the object equivalent of the current integer.
(You have to store objects, e.g. Strings, since Lists store Objects not ints.)


---------------------------------------------------------------------------


[Problem is from Association for Computing Machinery, 2008-2009.]

Patrick has a four function calculator (add, subtract, multiply, divide). Unfortunately, the display is broken, but the calculator still functions. This calculator has a display constructed from "seven-segment" digits.

This particular calculator only displays three digits of accuracy:
integers from -999 to 999, inclusive. There are no decimal points since all math is performed using integers (with truncation for the divisions).
[Truncation means remove the fraction, don't round up or down. I.e., the calculator's division works like Java's "int/int" division.]

Example: the number -112 lights up ten segments (2 segments for the "1", 2 segments for the next "1", 5 segments for the "2", plus 1 extra segment for the "-" sign).

(Like on real calculators, negative numbers get a "-", but there's no "+" sign in front of positive numbers which are displayed.)
(For ease, assume that no value will ever contain numbers with leading zeroes.)

In order to prove that the calculator still operates, the back cover is removed and an ammeter is attached to the display. An ammeter measures the current consumed by the device, and each segment of a digit consumes five milliamps per segment. Thus, to display a number such as "798" the current consumption can be predicted as follows:

Digit 7: 3 segments lit = 15 milliamps
Digit 9: 6 segments lit = 30 milliamps
Digit 8: 7 segments lit = 35 milliamps
Total = 80 milliamps

Of course, the number "798" consumes the same amount of current as "897", or "-891", etc.

Patrick wishes to prove that the functionality of the calculator is intact, so he enters "949" and measures 80 milliamps. Then he pushes the subtract key. Next he enters "51" and measures 35 milliamps. After pressing the "=" key, the result should be "898", measuring 100 milliamps.

As a second example, he enters "-5", then pushes the addition key. He then enters "-4" and presses equal. The answer is "-9". The measurements were 30 milliamps, 25 milliamps, and 35 milliamps.

Patrick is now presented with the following problem:

Given the current consumption (milliamps) of operand X, operand Y, and result Z, and given unknown operation Op (either +, -, *, or /), determine the number of possible solutions (if any) for

X Op Y = Z

Note that in all cases there are only three digits on the display. Although the input values of 80, 35, and 100 potentially could represent 949*13 = 12337, this is not possible because 12337 is too large for the three digit display to hold.

Example:
If the user inputs values of X's milliamps=25, Y's milliamps=25, Z's milliamps=20, your program should output 5, since there are 5 possible results:
-11 - -4 = -7
-4 - 3 = -7
2 + 2 = 4
2 * 2 = 4
71 / 17 = 4

Some input combinations have no result. For example, for the values 35, 10, 10 there is no possible answer (since there are no leading zeroes).

Your program's input will only consist of positive integer values for X's milliamps, Y's milliamps, Z's milliamps.

For the user's input, your program is to determine the number of possible solutions and output that number.

Sample Inputs and Outputs

25 25 20 ---> should output 5
35 10 10 ---> should output 0
15 20 30 ---> should output 9
30 65 65 ---> should output 819



Seven-segment display
The digits
Citera
2009-05-08, 10:10
  #2
Medlem
Länkade listor är väldigt vanligt oavsett vilket land man är i. Det är bara en datastruktur.

Det framgår inte av din beskrivning hur många segment olika siffror lyser upp.

I den extra hinten, varifrån kommer siffran 23?
Citera
2009-05-08, 12:08
  #3
Medlem
Först gör du en lista med strömförbrukningen för alla värden. Det är redan givet.
Citat:
Check all the integers from -999 to 999.
For each of those integers, compute the number of calculator "segments", k,
required for it.
Kalla den för nått smart tex. currentDraw.
Sen en lista till med alla gånger x förekommer i currentDraw. Spara värdet i den listan vi kan kalla för inputX. Vi sparar värdet för det är det vi är intresserade av.

Gör samma för inputY.

Det enklaste hade nog varit att spara dom i en tvådimensionell array men eftersom vi ska ha listor så använder vi det.

Sen utför vi dom fyra operationer på alla möjliga kombinationer i dom två listorna och för varje kollar vi om vi fått ett giltigt resultat. Det vill säga om resultatet finns med i currentDraw. Gör en contains(Object obj) funktion för enkelhetens skull. Spara giltiga svar i en ny lista kallad tex. validAnswers

Enklast är ju helt enkelt att göra alla additioner först,multiplikationer sen etc.
Eftersom a+b = b+a och a*b = b*a så kan du spara lite tid genom att inte jämföra dom igen. Det går inte med subtraktion och division.

Du använder givetvis Integer klassen för listorna.

Frågor ?
Citera
2009-05-08, 13:15
  #4
Medlem
Du kan ju fråga din föreläsare varför han kodar biblioteksfunktioner själv och plågar er med.
Citera
2009-05-08, 14:12
  #5
Moderator
Protons avatar
Säger detsamma, om ni nu ska använda er av länkade listor, exakt vad är det för fel på den länkade lista som finns som standard i Java? Troligen är den betydligt bättre implementerad med.....

http://java.sun.com/j2se/1.5.0/docs/...inkedList.html

Den här kan ju vara trevlig att kika i då å då med...

http://java.sun.com/j2se/1.5.0/docs/api/index.html
__________________
Senast redigerad av Proton 2009-05-08 kl. 14:15.
Citera
2009-05-08, 14:12
  #6
Medlem
gothxxs avatar
Citat:
Ursprungligen postat av Katalysator
Du kan ju fråga din föreläsare varför han kodar biblioteksfunktioner själv och plågar er med.

Lättare att läsa den koden själv och förstå principen bakom just den list funktionen?

Annars håller jag med att man skall använda det som finns eftersom det är noga testat för att inte kracha osv.
Citera
2009-05-12, 06:16
  #7
Medlem
virre_01s avatar
Citat:
Ursprungligen postat av SixtenSune
Först gör du en lista med strömförbrukningen för alla värden. Det är redan givet.

Kalla den för nått smart tex. currentDraw.
Sen en lista till med alla gånger x förekommer i currentDraw. Spara värdet i den listan vi kan kalla för inputX. Vi sparar värdet för det är det vi är intresserade av.

Aha okay. Sorry, men jag känner inte att jag är riktigt med här.

Jag ska alltså göra en loop som kollar alla värden mellan -999 och 999. Men vad exakt ska jag kolla efter? Antagligen är väl det så att jag ska komma om talet har lika många miliamps som talet som vart inputted. Det låter inte som att det är vidare memory efficient. Hur gör jag det bättre?
Citera
2009-05-12, 09:52
  #8
Medlem
Citat:
Ursprungligen postat av virre_01
Antagligen är väl det så att jag ska komma om talet har lika många miliamps som talet som vart inputted.
Precis,det är ju givet i uppgiften.
Citat:
Ursprungligen postat av virre_01
Det låter inte som att det är vidare memory efficient. Hur gör jag det bättre?
Det är 4 * 2000 = 2 kilobyte vi snackar om här. Och du behöver använda dom värdena om och om igen. Du kommer spara massor med CPU kraft genom att spara dom istället för att räkna ut dom igen. Så du byter en massa beräkningskraft mot 2 kilobyte minne. Ett bra byte i min bok.
Dessutom är det givet i uppgiften.
Citera
2009-05-17, 01:52
  #9
Medlem
virre_01s avatar
Ah okay, nu har jag fått några fler rader till mitt program
Det ser ut såhär nu:
Kod:
import sdsu.io*;
public class 
HW7
{

        public static List[] list = new List[
23];

        
int x Console.readLine("Input X's milliamps");
        
int y Console.readLine("Input Y's milliamps");
        
int z Console.readLine("inout Z's milliamps");

        
5;
        
5;
        
5;

        
int miliX 0;

        for(
int i = -999999i++)
        {
                for(
int k 0k<3,k++)
                {
                 
int c s.charAt(k);

                 if(
== -)
                  {
miliX++}
                 if else( 
== 0)
                  {
miliX miliX +6;}
                 if else( 
== 1)
                  {
miliX miliX +2;}
                 if else( 
== 2)
                  {
miliX miliX +5;}
                 if else( 
== 3)
                  {
miliX miliX +5;}
                 if else( 
== 4)
                  {
miliX miliX +4;}
                 if else( 
== 5)
                  {
miliX miliX +5;}
                 if else( 
== 6)
                  {
miliX miliX +6;}
                 if else( 
== 7)
                  {
miliX miliX +3;}
                 if else( 
== 8)
                  {
miliX miliX +7;}
                 if else( 
== 9)
                  {
miliX miliX +6;}


                }



        } 

Först och främst: Är jag på rätt spår?
Funkar det jag har gjort och hur går jag till väga nu? Jag antar att jag behöver checka om antalet miliamps överstämmer med det som vart inputted och sen lägga in det i en av listorna.

Tack igen för alla svaren hitilst och tack på förhand för kommande svar
Citera
2009-05-17, 03:30
  #10
Moderator
Protons avatar
Antar att du menar else if och inte if else?

Du borde nog i detta fallet även fundera på om du inte, för läsbarhetens skull, borde använda en switch istället:

Kod:
//...massa kod....

int c s.charAt(k); 
switch(
c){
     case 
0:  miliX miliX +6; break;
     case 
1miliX miliX +2; break;
     
//fortsätter sådär ända tills den här kommer....
     
default: miliX++;


Den där kommer göra samma sak som dina else if (om de hade varit rättskrivna) men jag tycker iaf det är mer lättläst så. "default" är den kodraden som körs om INGEN annan av case-satserna körs. Vill man inte ha en defaullt så tar man helt enkelt bort den och byter ut den mot nåt annat.

Tror dessutom inte att du kan tilldela en int ett - bara, utan ett -1 hade nog kunnat funka bättre i detta fall, fast det ville du ju inte ha

Så, lite mer kod för dej där. Din typkonvertering verkar lite skum dessutom. charAt kommer ge dej en char, som du försöker stoppa i en int. Blir det verkligen rätt det?
Citera
2009-05-17, 12:08
  #11
Medlem
Det kan vara en poäng att lärarens egenskrivna kod är mer lättilgänglig, men jag tror det mer beror på att han vill göra allt själv. Se bara på instruktionerna i uppgiften -- så gott som allt är ju givet på förhand in i minsta detalj; datastrukturer är stipulerade, algoritmer är fastlagda. Det enda som är kvar åt eleverna är att knappa in bokstäverna i datormaskinen.

Angående ditt senaste problem, så är milliX ett dåligt namn på segmentantalet. Jag skulle valt att koda segmenträknandet i en array

int seg[10] = { 6, 2, 5, 5, 4, 5, 6, 3, 7, 6 };

och använt modulu 10 av absolutbeloppet av talet efter att jag eventuellt lagt till ett för minustecknet om tal<0. Då gäller det i och för sig att se upp för specialfallet 0, som är det enda tal som har en inledande nolla (sig själv).
Citera
2009-05-18, 05:27
  #12
Medlem
virre_01s avatar
aha okay. Jag kollade vad ni svarade och har nu gjort några ändringar. Jag har dock beslutat att ha kvar mina if och else if för att det är så min lärare har lärt ut till oss än så länge.

Nu ser mitt program ut såhär:

Kod:
import sdsu.io*;
public class 
HW7
{

        public static List[] list = new List[
23];

        
int x Console.readLine("Input X's milliamps");
        
int y Console.readLine("Input Y's milliamps");
        
int z Console.readLine("inout Z's milliamps");

        
5;
        
5;
        
5;


        for(
int i = -999999i++)
        {
                
int miliX 0;

                for(
int k 0k<3,k++)
                {
                 
int k s.charAt(k);
                 
int c = (int)- (int)'0';

                 if ( 
0)
                  {
miliX++;}

                 if ( 
== 0)
                  {
miliX miliX +6;}
                 else if( 
== 1)
                  {
miliX miliX +2;}
                 else if( 
== 2)
                  {
miliX miliX +5;}
                 else if( 
== 3)
                  {
miliX miliX +5;}
                 else if( 
== 4)
                  {
miliX miliX +4;}
                 else if( 
== 5)
                  {
miliX miliX +5;}
                 else if( 
== 6)
                  {
miliX miliX +6;}
                 else if( 
== 7)
                  {
miliX miliX +3;}
                 else if( 
== 8)
                  {
miliX miliX +7;}
                 else if( 
== 9)
                  {
miliX miliX +6;}
                }

                if ( 
miliX == x)
                 {list[
1].insertAtBack(?);}
                else if ( 
miliX == y)
                 {list[
2].insertAtBack(?);}
                else if ( 
miliX == z)
                 {list[
3].insertAtBack{?);}

        }



Jag ändrade lite småfel och la till lite saker. Jag försöker nu lägga in tal i mina listor. Blir det lättast om jag lägger in talen i nån särskild lista och kommer det verkligen lägga in den i listan om jag kodar det som jag har gjort nu?

Sen så är jag inte säker på vad jag ska ersätta frågetecknerna med för att få in rätt tal i listorna.

Tack igen för svaren och all hjälp
Citera
  • 1
  • 2

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in