I have this homework assignment where i have to input a text file into my java program. the file is a "bed sensor", and tells you if the person is in a deep sleep, a restless sleep, or interrupted sleep(awake), with 0s, 1s, and 2s respectively. each line has a 0, 1, or 2 and there are 86,400 lines (one line for each second of the day).
I have figured out most of the assignment but one part i cannot figure out how to code.
My problem is i have to figure out when the person falls asleep and then output "Sleep time: (answer) hours after midnight".
i've been using counters and if statements and i would like to continue along this path if possible. i've attached my code.. and i feel like this should be pretty simple to figure out based on what i've already done... i just cannot wrap my head around it. i would appreciate any help or advice. thanks
public static void main(String[] args) {
try {
File sleepDataFile = new File("/Users/homeWork3/sleep_data.csv");
Scanner sleepData = new Scanner(sleepDataFile); // scans the data from the file into this java program
double totalSecondsCounter = 0, wakeCounter = 0, timeAwakeCounter = 0, timeAsleepCounter = 0, deepSleepCounter = 0, restlessSleepCounter = 0, interruptedSleepCounter = 0;
double wakeUpTime = 0, sleepTime = 0;
double sleepQuality = 0;
boolean inSleep = false;
while (sleepData.hasNextLine()) // this loop writes data to java as long as there is a next line
{
String data = sleepData.nextLine(); // converts the file data to strings
double val = Double.parseDouble(data); // changes string type to double type
totalSecondsCounter++;
if (inSleep == true) {
timeAsleepCounter++;
}
if (inSleep == false) {
timeAwakeCounter++;
}
if (val == 0) //deep sleep
{
deepSleepCounter++;
inSleep = true;
wakeCounter = 0;
}
if (val == 1) //restless sleep
{
restlessSleepCounter++;
inSleep = true;
wakeCounter = 0;
}
if (val == 2) // interrupted sleep / awake
{
wakeCounter++;
inSleep = false;
}
if (val == 2 && wakeCounter < 1800) {
interruptedSleepCounter++;
inSleep = true;
}
if (val == 2 && wakeCounter > 1800) {
inSleep = false;
}
if (wakeCounter == 1800) // 1800 seconds = 30 minutes. counter is set for 30 min of interrupted sleep.
{
wakeUpTime = totalSecondsCounter;
}
if (val != 2) {
}
}
sleepData.close();
System.out.println("Sleep Report for 24 hour period.");
System.out.println("----------------------------------------------------------");
System.out.println("Wake Time: \t\t\t\t" + wakeUpTime / 60 / 60 + "\t hours after midnight");
System.out.println("Sleep Time: \t\t\t\t" + sleepTime / 60 / 60 + "\t\t\t hours after midnight");
System.out.println("Duration of Deep Sleep: \t\t" + deepSleepCounter / 60 / 60 + "\t hours");
System.out.println("Duration of Restless Sleep: \t\t" + restlessSleepCounter / 60 / 60 + "\t hours");
System.out.println("Duration of Interrupted Sleep: \t\t" + interruptedSleepCounter / 60 / 60 + "\t hours");
} catch (FileNotFoundException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
I'll just give you a (comprehensive) hint, since this is a homework question.
My problem is i have to figure out when the person falls asleep and then output "Sleep time: (answer) hours after midnight".
First of all, you're going to want to initialize two variables before your while loop:
Some boolean flag variable hasFallenAsleepYet
Some double variable fallenAsleepTime
Like so:
boolean hasFallenAsleepYet = false;
double fallenAsleepTime;
Now, inside of your while loop, as you're iterating through sleepData, you're going to want to count the time taken until the person falls asleep, then stop counting.
if(!hasFallenAsleepYet) {
if(val == someInteger || val == someOtherInteger){ // some condition to tell if the person is asleep
hasFallenAsleepYet = true;
fallenAsleepTime = totalSecondsCounter;
}
}
I'll leave you to figure out what the numbers someInteger and someOtherInteger are, but you should be able to figure it out quickly. They key takeaway here is that you need to initialize some flag variable, so that you stop keeping track of fallenAsleepTime after a certain condition is met.
This is my code to update the Status:
String[] status = new String[] {"Version: 1.5.0", "https://discord.gg/arWEM2h", "Love Backxtar", "You want me!", "Type: ~help", "User Counter: %members"};
int next = 60;
public void onSecond() {
if(next%5 == 0) {
if(!hasStarted) {
hasStarted = true;
StatChannelCommand.onStartUp();
}
Random rand = new Random();
int i = rand.nextInt(status.length);
shardMan.getShards().forEach(jda -> {
String text = status[i].replaceAll("%members", "" + jda.getUsers().size());
jda.getPresence().setActivity(Activity.playing(text));
});
StatChannelCommand.checkStats();
if(next == 0) {
next = 60;
}
}
else {
next--;
}
}
But the String is running every second. I thought it was every 5 seconds. I did 60 sec % 5. What is wrong with this code?
When you enter the method onSecond() for the first time, the condition next%5 == 0 will be true. The variable next will not be updated, because this happens only in the else part. So, on next run of the method next will still be 60.
I am working on an Virtual-Reality client for a Java API
I am not able to read the second command (1 byte ord) from the Java Server-Socket.
This is my java code:
package de.e_nexus.vr.server;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import de.e_nexus.vr.server.codes.Client2ServerCode;
import de.e_nexus.vr.server.listeners.VRClientRequestAppInfo;
import de.e_nexus.vr.server.listeners.VRClientStatusListener;
import de.e_nexus.vr.server.listeners.VRExceptionListener;
import de.e_nexus.vr.server.mesh.Mesh;
import de.e_nexus.vr.server.mesh.MeshOutputStream;
public class VRServer extends ServerSocket {
private static final Charset LATIN1;
static {
LATIN1 = Charset.forName("latin1");
}
private final Set<VRClientStatusListener> statusListeners = new LinkedHashSet<VRClientStatusListener>();
private final Set<VRExceptionListener> exceptionListeners = new LinkedHashSet<VRExceptionListener>();
private final Set<VRClientRequestAppInfo> infoListeners = new LinkedHashSet<VRClientRequestAppInfo>();
private final Set<Mesh> toSend = new LinkedHashSet<Mesh>();
private class Worker extends Thread {
private boolean running = true;
public void run() {
try {
setSoTimeout(50);
} catch (SocketException e) {
e.printStackTrace();
}
while (running) {
cycle();
}
T = null;
};
}
private Worker T;
public VRServer() throws IOException {
super(8779);
}
public void addVRClientStatusListener(VRClientStatusListener vrClientStatusListener) {
statusListeners.add(vrClientStatusListener);
}
public void addVRExceptionListener(VRExceptionListener listener) {
exceptionListeners.add(listener);
}
public void start() {
if (T == null) {
T = new Worker();
T.start();
}
}
public void stop() {
T.running = false;
}
public boolean isStopping() {
return T != null && !T.running;
}
protected void cycle() {
try {
Socket s = accept();
log("Connected");
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
int read = in.read();
if (read == -1) {
log("Closed unexpectedly "+in.available());
} else {
Client2ServerCode code = Client2ServerCode.read(read);
log("Read " + code + " ord(" + read + ")");
switch (code) {
case GET_APP_INFO:
StringBuilder sb = new StringBuilder();
for (VRClientRequestAppInfo vrClientRequestAppInfo : infoListeners) {
sb.append(vrClientRequestAppInfo.getLatin1Title());
}
System.out.println(sb);
outLenString(out, sb.toString());
break;
case GET_INCOMING_MESH:
int count = Math.min(toSend.size(), 100);
out.write(count);
System.out.println("wrote incomming mesah count");
for (int i = 0; i < count; i++) {
Iterator<Mesh> iterator = toSend.iterator();
Mesh mesh = iterator.next();
iterator.remove();
ByteArrayOutputStream buff = new ByteArrayOutputStream();
MeshOutputStream mos = new MeshOutputStream(buff);
mos.writeMesh(mesh);
mos.flush();
outLenString(out, buff.size() + "");
out.write(buff.toByteArray());
}
out.flush();
default:
break;
}
System.out.println("Thanks");
}
s.close();
} catch (Exception e) {
notifyExceptionInCycle(e);
}
}
private void log(String string) {
System.out.println(string);
}
private void outLenString(OutputStream out, String string) throws IOException {
byte[] b = string.getBytes(LATIN1);
int length = b.length;
out.write(length);
out.write(b);
out.flush();
}
private void notifyExceptionInCycle(Exception e) {
boolean handled = false;
for (VRExceptionListener vrExceptionListener : exceptionListeners) {
try {
vrExceptionListener.handle(e);
handled = true;
} catch (Exception ex) {
ex.addSuppressed(e);
ex.printStackTrace();
}
}
if (!handled) {
e.printStackTrace();
}
}
public Thread getThread() {
return T;
}
public void addInfoListener(VRClientRequestAppInfo l) {
infoListeners.add(l);
}
public void addMesh(Mesh m) {
toSend.add(m);
}
}
The Client2ServerCode is this:
package de.e_nexus.vr.server.codes;
public enum Client2ServerCode {
GET_APP_INFO, GET_INCOMING_MESH;
public static Client2ServerCode read(int read) {
for (Client2ServerCode c : values()) {
if (c.ordinal() == read) {
return c;
}
}
return null;
}
}
And this is my AGK Basic code
//******************************************************
// AGKVR Demo 1 - Castle Basic
//******************************************************
//This demo application will help you get to know AGKVR
SetErrorMode(0)
SetWindowTitle('VR')
//Load the AGKVR plugin
#import_plugin AGKVR
GET_APP_INFO as integer = 0
sock as integer
sock = ConnectSocket('127.0.0.1',8779,1000)
if sock = 0
message ('Timeout while connecting!')
end
endif
sleep(200)
if GetSocketConnected (sock) <> 1
message ('Not connected!')
end
endif
rem connected!
SendSocketByte(sock, GET_APP_INFO)
FlushSocket(sock)
if GetSocketConnected (sock) <> 1
message ('Could not request for app-info from server!')
end
endif
readTitle(sock)
DeleteSocket(sock)
sock = ConnectSocket('127.0.0.1',8779,1000)
if sock = 0
message ('Timeout while connecting!')
end
endif
readMesh(sock)
DeleteSocket(sock)
// <---------------------- below this is old example code, you can ignore it
//Init App
SetSyncRate(0, 0)
SetWindowSize( 1024, 768, 0 )
SetScissor(0, 0, 0, 0)
//Hand Model ID numbers
RightHandModel as integer = 100
LeftHandModel as integer = 101
HandModelImg as integer = 100
//Generate Mipmaps for nicer looking textures
SetGenerateMipmaps( 1 )
//Create Skybox
SetSkyBoxHorizonColor( 200, 200, 255 )
SetSkyBoxHorizonSize( 10, 2 )
SetSkyBoxSkyColor( 50, 50, 255)
SetSkyBoxSunColor( 255,255,255 )
SetSkyBoxVisible( 1 )
SetSkyBoxSunSize( 1, 3.0 )
SetSkyBoxSunVisible( 1 )
//Load Hand Models
//---------------------------
//Right Hand
LoadObjectWithChildren(RightHandModel,"RHand.FBX")
SetObjectScale(RightHandModel,1.15,1.15,1.15)
SetObjectPosition(RightHandModel,0.0,0.0,-0.07)
SetObjectRotation(RightHandModel,0.0,180.0,90.0)
FixObjectPivot(RightHandModel)
SetObjectAnimationSpeed(RightHandModel,20)
LoadImage(HandModelImg,"Hand.png")
SetObjectImage(RightHandModel,HandModelImg,0)
SetObjectVisible(RightHandModel,0)
SetObjectCollisionMode(RightHandModel,0)
//Left Hand
LoadObjectWithChildren(LeftHandModel,"LHand.FBX")
SetObjectScale(LeftHandModel,1.15,1.15,1.15)
SetObjectPosition(LeftHandModel,0.0,0.0,-0.07)
SetObjectRotation(LeftHandModel,0.0,180.0,270.0)
FixObjectPivot(LeftHandModel)
SetObjectAnimationSpeed(LeftHandModel,20)
SetObjectImage(LeftHandModel,HandModelImg,0)
SetObjectVisible(LeftHandModel,0)
SetObjectCollisionMode(LeftHandModel,0)
//Call function to load world models
LoadWorld( )
//Set the Camera Range in AGKVR
//It is necessary to use this command for setting the camera's range instead of the standard AGK SetCameraRange command
AGKVR.SetCameraRange( 0.01, 1000.0 )
//Initialiaze AGKVR
//------------------------------------------------
// The parameters are the Right and Left Eye image ID's that will be used to render to the HMD
InitError As Integer
RightEyeImg As Integer = 500
LeftEyeImg As Integer = 501
InitError = AGKVR.Init( RightEyeImg, LeftEyeImg )
// InitError = 0: SUCCESS!
// InitError = 1: Unable to init VR runtime
// InitError = 2: Compositor initialization failed.
//This command will lock the player's heading direction
//to follow the turn angle of the HMD. This would be common in FPS games, where
//you want the forward moving direction's turn angle to change based on where the
//player is looking. LockPlayerTurn is ON(1) by default
AGKVR.LockPlayerTurn( 1 )
//This command will lock the player's heading direction (forward on the Z axis)
//to follow the pitch angle of the HMD. This would be useful in a freeflight style game
//where you want the forward moving direction's pitch angle to change based on where the
//player is looking. LockPlayerPitch is OFF(0) by default
AGKVR.LockPlayerPitch( 0 )
CreateVector3(1,2,3.4)
do
//Get AGKVR's Player container's current Position, which will be used later for collision purposes:
PlayerPosX as float
PlayerPosY as float
PlayerPosZ as float
PlayerPosX = AGKVR.GetPlayerX(): `
PlayerPosY = AGKVR.GetPlayerY()
PlayerPosZ = AGKVR.GetPlayerZ()
//Control Player Turn Angle with Left Controller Joystick
valx as float
valz as float
valx = AGKVR.LeftController_JoyX( )
AGKVR.RotatePlayerLocalY( valx )
//Control Player Movement based on Right Controller Joystick
valx = AGKVR.RightController_JoyX( )
valz = AGKVR.RightController_JoyY( )
AGKVR.MovePlayerLocalZ( valz*0.06 )
AGKVR.MovePlayerLocalX( valx*0.06 )
//Move with the Keyboard
if GetRawKeyState(87) = 1
AGKVR.MovePlayerLocalZ( 0.1 )
endif
if GetRawKeyState(83) = 1
AGKVR.MovePlayerLocalZ( -0.1 )
endif
if GetRawKeyState(65) = 1
AGKVR.MovePlayerLocalX( -0.1 )
endif
if GetRawKeyState(68) = 1
AGKVR.MovePlayerLocalX( 0.1 )
endif
//Collision
New_PlayerPosX as float
New_PlayerPosY as float
New_PlayerPosZ as float
//Get the Player's ground position now that any movement has occured.
New_PlayerPosX = AGKVR.GetPlayerX()
New_PlayerPosY = AGKVR.GetPlayerY()
New_PlayerPosZ = AGKVR.GetPlayerZ()
//Check for collision from previous position to new position (add the radius to the Y position)
if ObjectSphereSlide(0,PlayerPosX,PlayerPosY+0.5,PlayerPosZ,New_PlayerPosX,New_PlayerPosY+0.5,New_PlayerPosZ,0.5)>0
//Get the collision point (Subtract the collision radius from the Y position)
New_PlayerPosX = GetObjectRayCastSlideX(0)
New_PlayerPosY = GetObjectRayCastSlideY(0)-0.5
New_PlayerPosZ = GetObjectRayCastSlideZ(0)
//Set the player position to the collision point
AGKVR.SetPlayerPosition( New_PlayerPosX, New_PlayerPosY, New_PlayerPosZ )
endif
//Control Hand animation based on Trigger feedback
Rvalue as float
Lvalue as float
Rvalue = AGKVR.RightController_Trigger( )
Lvalue = AGKVR.LeftController_Trigger( )
SetObjectAnimationFrame(RightHandModel, GetObjectAnimationName( RightHandModel, 1 ), GetObjectAnimationDuration(RightHandModel,GetObjectAnimationName( RightHandModel, 1 ))*Rvalue,0)
SetObjectAnimationFrame(LeftHandModel, GetObjectAnimationName( LeftHandModel, 1 ), GetObjectAnimationDuration(LeftHandModel,GetObjectAnimationName( LeftHandModel, 1 ))*Lvalue,0)
//Now that the player's position and orientation has been modified,
//the UpdatePlayer command is called to update all the components of
//AGKVR's player framework
AGKVR.UpdatePlayer( )
//Position Hand Objects
if AGKVR.RightControllerFound( ) = 1
SetObjectPosition( RightHandModel, AGKVR.GetRightHandX(), AGKVR.GetRightHandY(), AGKVR.GetRightHandZ())
SetObjectRotation( RightHandModel, AGKVR.GetRightHandAngleX(), AGKVR.GetRightHandAngleY(), AGKVR.GetRightHandAngleZ())
SetObjectVisible( RightHandModel, 1 )
else
SetObjectVisible( RightHandModel, 0 )
endif
if AGKVR.LeftControllerFound( ) = 1
SetObjectPosition( LeftHandModel, AGKVR.GetLeftHandX(), AGKVR.GetLeftHandY(), AGKVR.GetLeftHandZ())
SetObjectRotation( LeftHandModel, AGKVR.GetLeftHandAngleX(), AGKVR.GetLeftHandAngleY(), AGKVR.GetLeftHandAngleZ())
SetObjectVisible( LeftHandModel, 1 )
else
SetObjectVisible( LeftHandModel, 0 )
endif
//This command renders to the HMD.
AGKVR.Render( )
//The camera's position and rotation will determine what is displayed on the monitor, not the HMD
SetCameraPosition( 1, AGKVR.GetHMDX(), AGKVR.GetHMDY(), AGKVR.GetHMDZ())
SetCameraRotation( 1, AGKVR.GetHMDAngleX(), AGKVR.GetHMDAngleY(), AGKVR.GetHMDAngleZ())
Print( ScreenFPS() )
//Display some controller feedbacks on the monitor
if AGKVR.RightController_Grip() = 1
Print( "Right Grip Pressed" )
endif
if AGKVR.LeftController_Grip() = 1
Print( "Left Grip Pressed" )
endif
if AGKVR.LeftController_Button1() = 1
Print( "Left Button 1 Pressed" )
endif
if AGKVR.RightController_Button1() = 1
Print( "Right Button 1 Pressed" )
endif
if AGKVR.LeftController_Button2() = 1
Print( "Left Button 2 Pressed" )
endif
if AGKVR.RightController_Button2() = 1
Print( "Right Button 2 Pressed" )
endif
//Sync to update the monitor display (the HMD display is updated through AGKVR's Render Command
//so this Sync is not necessary to for rendering to the HMD)
Sync()
loop
function readTitle(s)
count as integer
count=0
sleep (5)
while count < 100
if GetSocketBytesAvailable(s) > 0
exit
endif
sleep(10)
inc count
endwhile
if count = 100
message ('Timeout while read title!')
end
endif
appTitleLength as integer
appTitleLength = GetSocketByte(s)
txt as string
txt=''
for i = 0 to appTitleLength
txt = txt + chr(GetSocketByte(s))
next i
SetWindowTitle(txt)
endfunction
function readMesh(s)
if SendSocketByte(s, 1) = 1
message('Could not place command to buffer')
end
endif
if FlushSocket(s) = 1
message('Could not send the buffered command to the server')
end
endif
count as integer
count = 0
message('flushed')
sleep (5)
while count < 100
if GetSocketBytesAvailable(s) > 0
exit
endif
sleep(4)
inc count
endwhile
if count = 100
message ('Timeout while read incomming mesh count!')
end
endif
// in count is the mesh size stored.
for i = 0 to count
lenSize as integer
count = 0
while count < 100
if GetSocketBytesAvailable(s) > 0
exit
endif
sleep(5)
inc count
endwhile
if count = 100
message('Timeout while read size of incomming mesh memblock.')
end
endif
lenSize = GetSocketByte(s)
lenTxt as String
lenTxt=''
for j = 0 to lenSize
lenTxt=lenTxt + chr(GetSocketByte(s))
next j
lenSize = val(lenTxt)
count = 0
while count < 100
if GetSocketBytesAvailable(s) = lenSize
exit
endif
sleep(5)
inc count
endwhile
if count = 100
message('Timeout while read incomming mesh memblock.')
end
endif
blk as integer
blk = CreateMemblock(lenSize)
for j = 0 to lenSize
SetMemblockByte(blk, j, GetSocketByte(s))
next j
CreateObjectFromMeshMemblock(blk)
next i
endfunction
function LoadWorld( )
scaleval as float = 0.037
LoadObject(1,"Castle.fbx")
SetObjectScale(1,scaleval,scaleval,scaleval)
LoadImage(1,"banquet hall_D.png")
LoadImage(2,"portcullis_D.png")
LoadImage(3,"stable_D.png")
LoadImage(4,"well_D.png")
LoadImage(5,"wall.png")
LoadImage(6,"tower.png")
LoadImage(7,"kings apartment_D.png")
SetObjectMeshImage( 1, 1, 2, 0 )
SetObjectMeshImage( 1, 2, 5, 0 )
SetObjectMeshImage( 1, 4, 6, 0 )
SetObjectMeshImage( 1, 5, 7, 0 )
SetObjectMeshImage( 1, 6, 1, 0 )
SetObjectMeshImage( 1, 7, 3, 0 )
SetObjectMeshImage( 1, 8, 4, 0 )
SetObjectMeshImage( 1, 9, 1, 0 )
//Field
LoadImage(50,"TerrainGrass.png")
LoadObject(50,"field.fbx")
SetObjectRotation(50,0,0,0)
SetObjectScale(50,5,5,5)
SetObjectImage(50,50,0)
SetObjectMeshUVScale( 50, 1, 0, 100, 100 )
SetImageWrapU(50,1)
SetImageWrapV(50,1)
endfunction
The App-info is read successfully but Java does not recieve the first byte of the second command, why not?
The socket is not allowed as parameter. I put the open socket inside the functions and it works.
This is a homework question.
The code compiles, but in the test case, 2 is outputting as perfect, which it is not.
I cannot use an array. I cannot use Math.min() or Math.max(). Purely conditionals and loops.
My professor says I need to only test for divisors up to and including n/2 but when I do that, I still get the 2 as a perfect number.
Any help would be appreciated.
// Project2.java
import java.io.*; // BufferedReader
import java.util.*; // Scanner
public class Project2
{
public static void main (String args[]) throws Exception
{
// ALWAYS TEST FIRST TO VERIFY USER PUT REQUIRED CMD ARGS
if (args.length < 3)
{
System.out.println("\nusage: C:\\> java Project2 <input file name> <lo> <hi>\n\n");
// i.e. C:\> java Project2 P2input.txt 1 30
System.exit(0);
}
String infileName = args[0]; // i.e. L2input.txt
int lo = Integer.parseInt( args[1] ); // i.e. 1
int hi = Integer.parseInt( args[2] ); // i.e. 30
// STEP #1: OPEN THE INPUT FILE AND COMPUTE THE MIN AND MAX. NO OUTPUT STATMENTS ALLOWED
Scanner infile = new Scanner( new File(infileName) );
int min,max;
min=max=infile.nextInt(); // WE ASSUME INPUT FILE HAS AT LEAST ONE VALUE
while ( infile.hasNextInt() )
{
// YOUR CODE HERE FIND THE MIN AND MAX VALUES OF THE FILE
// USING THE LEAST POSSIBLE NUMBER OF COMPARISONS
// ASSIGN CORRECT VALUES INTO min & max INTHIS LOOP.
// MY CODE BELOW WILL FORMAT THEM TO THE SCREEN
// DO NOT WRITE ANY OUTPUT TO THE SCREEN
int number = infile.nextInt();
if ( number < min )
{
min = number;
}
else if ( number > max )
{
max = number;
}
}
System.out.format("min: %d max: %d\n",min,max); // DO NOT REMOVE OR MODIFY IN ANY WAY
// STEP #2: DO NOT MODIFY THIS BLOCK
// TEST EVERY NUMBER BETWEEN LO AND HI INCLUSIVE FOR
// BEING PRIME AND/OR BEING PERFECT
for ( int i=lo ; i<=hi ; ++i)
{
System.out.print( i );
if ( isPrime(i) ) System.out.print( " prime ");
if ( isPerfect(i) ) System.out.print( " perfect ");
System.out.println();
}
} // END MAIN
// *************** YOU FILL IN THE METHODS BELOW **********************
// RETURNs true if and only if the number passed in is perfect
static boolean isPerfect( int n )
{
int sum = 0;
for(int i = 1; i <= n/2; i ++)
{
if(n%i == 0)
{
sum += i;
}
}
if (sum == n)
{
return true;
}
else
{
return false;
}
// (just to make it compile) YOU CHANGE AS NEEDED
}
// RETURNs true if and only if the number passed in is prime
static boolean isPrime( int n )
{
if (n < 3)
{
return false;
}
for(int i = 2; i <= n/2; i++)
{
if(n%i == 0)
{
return false;
}
}
return true;
}// (just to make it compile) YOU CHANGE AS NEEDED
}
OK, I found a bug, although it's not quite the bug you described.
static boolean isPrime( int n )
{
if (n < 3)
{
return false;
}
This will incorrectly list 2 as not prime, because it's less than 3.
Is it possible to convert the function go into the non-recursive function? Some hints or a start-up sketch would be very helpful
public static TSPSolution solve(CostMatrix _cm, TSPPoint start, TSPPoint[] points, long seed) {
TSPSolution sol = TSPSolution.randomSolution(start, points, seed, _cm);
double t = initialTemperature(sol, 1000);
int frozen = 0;
System.out.println("-- Simulated annealing started with initial temperature " + t + " --");
return go(_cm, sol, t, frozen);
}
private static TSPSolution go(CostMatrix _cm, TSPSolution solution, double t, int frozen) {
if (frozen >= 3) {
return solution;
}
i++;
TSPSolution bestSol = solution;
System.out.println(i + ": " + solution.fitness() + " " + solution.time() + " "
+ solution.penalty() + " " + t);
ArrayList<TSPSolution> nHood = solution.nHood();
int attempts = 0;
int accepted = 0;
while (!(attempts == 2 * nHood.size() || accepted == nHood.size()) && attempts < 500) {
TSPSolution sol = nHood.get(rand.nextInt(nHood.size()));
attempts++;
double deltaF = sol.fitness() - bestSol.fitness();
if (deltaF < 0 || Math.exp(-deltaF / t) > Math.random()) {
accepted++;
bestSol = sol;
nHood = sol.nHood();
}
}
frozen = accepted == 0 ? frozen + 1 : 0;
double newT = coolingSchedule(t);
return go(_cm, bestSol, newT, frozen);
}
This is an easy one, because it is tail-recursive: there is no code between the recursive call & what the function returns. Thus, you can wrap the body of go in a loop while (frozen<3), and return solution once the loop ends. And replace the recursive call with assignments to the parameters: solution=bestSol; t=newT;.
You need to thinkg about two things:
What changes on each step?
When does the algorithm end?
Ans the answer should be
bestSol (solution), newT (t), frozen (frozen)
When frozen >= 3 is true
So, the easiest way is just to enclose the whole function in something like
while (frozen < 3) {
...
...
...
frozen = accepted == 0 ? frozen + 1 : 0;
//double newT = coolingSchedule(t);
t = coolingSchedule(t);
solution = bestSol;
}
As a rule of thumb, the simplest way to make a recursive function iterative is to load the first element onto a Stack, and instead of calling the recursion, add the result to the Stack.
For instance:
public Item recursive(Item myItem)
{
if(myItem.GetExitCondition().IsMet()
{
return myItem;
}
... do stuff ...
return recursive(myItem);
}
Would become:
public Item iterative(Item myItem)
{
Stack<Item> workStack = new Stack<>();
while (!workStack.isEmpty())
{
Item workItem = workStack.pop()
if(myItem.GetExitCondition().IsMet()
{
return workItem;
}
... do stuff ...
workStack.put(workItem)
}
// No solution was found (!).
return myItem;
}
This code is untested and may (read: does) contain errors. It may not even compile, but should give you a general idea.