GTK# Eventbox MotionNotify not working - c#

I have an EventBox in my application for handling notify events (enternotify, motionNotify and LeaveNotify are the interestin events for me). Inside this EventBox is an HScale, for which I display tooltips depending on the mouse position for audio seeking. But the motion nofity event doesn't get fired.
Some code:
protected void ebAudiofileSeekerEnterNotifyEvent (object o, EnterNotifyEventArgs args)
{
log.debug("ebAudiofileSeekerEnterNotifyEvent called");
int x = -1;
int y = -1;
int intX = -1;
int intY = -1;
int originX;
int originY;
this.GetPosition(out originX, out originY);
Gdk.ModifierType modifierType = Gdk.ModifierType.None;
this.Screen.RootWindow.GetPointer(out x, out y, out modifierType);
this.hsAudiofileSeeker.TranslateCoordinates(this,this.hsAudiofileSeeker.Allocation.X,this.hsAudiofileSeeker.Allocation.Y,out intX,out intY);
double valueAtPos = ((x - (intX + originX)) / (this.hsAudiofileSeeker.Allocation.Width * 1.0)) * this.hsAudiofileSeeker.Adjustment.Upper * 1.0;
long ticksAtPosition = (this.objProgram.getAudioManager().getDuration().Ticks * (long)valueAtPos) / 100;
TimeSpan timeSpanAtPosition = TimeSpan.FromTicks(ticksAtPosition);
this.lblTooltipAudiofileSeeker.Text = (timeSpanAtPosition.Hours > 9 ? timeSpanAtPosition.Hours.ToString() : "0" + timeSpanAtPosition.Hours.ToString()) + ":" + (timeSpanAtPosition.Minutes > 9 ? timeSpanAtPosition.Minutes.ToString() : "0" + timeSpanAtPosition.Minutes.ToString()) + ":" + (timeSpanAtPosition.Seconds > 9 ? timeSpanAtPosition.Seconds.ToString() : "0" + timeSpanAtPosition.Seconds.ToString());
this.hsAudiofileSeeker.TooltipWindow.Move(x, intY + originY);
this.hsAudiofileSeeker.TooltipWindow.ShowAll();
}
protected void ebAudiofileSeekerMotionNotifyEvent (object o, MotionNotifyEventArgs args)
{
log.debug("ebAudiofileSeekerMotionNotifyEvent called");
int x = -1;
int y = -1;
int intX = -1;
int intY = -1;
int originX;
int originY;
this.GetPosition(out originX, out originY);
Gdk.ModifierType modifierType = Gdk.ModifierType.None;
this.Screen.RootWindow.GetPointer(out x, out y, out modifierType);
this.hsAudiofileSeeker.TranslateCoordinates(this,this.hsAudiofileSeeker.Allocation.X,this.hsAudiofileSeeker.Allocation.Y,out intX,out intY);
double valueAtPos = ((x - (intX + originX)) / (this.hsAudiofileSeeker.Allocation.Width * 1.0)) * this.hsAudiofileSeeker.Adjustment.Upper * 1.0;
long ticksAtPosition = (this.objProgram.getAudioManager().getDuration().Ticks * (long)valueAtPos) / 100;
TimeSpan timeSpanAtPosition = TimeSpan.FromTicks(ticksAtPosition);
this.lblTooltipAudiofileSeeker.Text = (timeSpanAtPosition.Hours > 9 ? timeSpanAtPosition.Hours.ToString() : "0" + timeSpanAtPosition.Hours.ToString()) + ":" + (timeSpanAtPosition.Minutes > 9 ? timeSpanAtPosition.Minutes.ToString() : "0" + timeSpanAtPosition.Minutes.ToString()) + ":" + (timeSpanAtPosition.Seconds > 9 ? timeSpanAtPosition.Seconds.ToString() : "0" + timeSpanAtPosition.Seconds.ToString());
this.hsAudiofileSeeker.TooltipWindow.Move(x, intY + originY);
}
protected void ebAudiofileSeekerLeaveNotifyEvent (object o, LeaveNotifyEventArgs args)
{
log.debug("ebAudiofileSeekerLeaveNotifyEvent called");
this.hsAudiofileSeeker.TooltipWindow.HideAll();
}
The ebAudiofileSeekerMotionNotifyEvent and ebAudiofileSeekerLeaveNotifyEvent work, but not the motion event, any ideas why? I'm a bit confused.
Thanks for your help.

Did you turn off event compression? Tooltips turn on POINTER_MOTION_HINT_MASK which messes with event compression.

I came accross this, setting the ebAudiofileSeeker AboveChild property to true and added the following code for the listeners:
protected void ebAudiofileSeekerEnterNotifyEvent (object o, EnterNotifyEventArgs args)
{
log.debug("ebAudiofileSeekerEnterNotifyEvent called");
if (Program.getInstance().getAudioManager().Duration > TimeSpan.Zero)
{
int x = -1;
int y = -1;
int intX = -1;
int intY = -1;
int originX;
int originY;
this.GetPosition(out originX, out originY);
Gdk.ModifierType modifierType = Gdk.ModifierType.None;
this.Screen.RootWindow.GetPointer(out x, out y, out modifierType);
this.hsAudiofileSeeker.TranslateCoordinates(this, this.hsAudiofileSeeker.Allocation.X, this.hsAudiofileSeeker.Allocation.Y, out intX, out intY);
double valueAtPos = ((x - (intX + originX)) / (this.hsAudiofileSeeker.Allocation.Width * 1.0)) * this.hsAudiofileSeeker.Adjustment.Upper * 1.0;
long ticksAtPosition = (Program.getInstance().getAudioManager().Duration.Ticks * (long)valueAtPos) / 100;
TimeSpan timeSpanAtPosition = TimeSpan.FromTicks(ticksAtPosition);
this.lblTooltipAudiofileSeeker.Text = (timeSpanAtPosition.Hours > 9 ? timeSpanAtPosition.Hours.ToString() : "0" + timeSpanAtPosition.Hours.ToString()) + ":" + (timeSpanAtPosition.Minutes > 9 ? timeSpanAtPosition.Minutes.ToString() : "0" + timeSpanAtPosition.Minutes.ToString()) + ":" + (timeSpanAtPosition.Seconds > 9 ? timeSpanAtPosition.Seconds.ToString() : "0" + timeSpanAtPosition.Seconds.ToString());
this.hsAudiofileSeeker.TooltipWindow.Move(x, intY + originY);
this.hsAudiofileSeeker.TooltipWindow.ShowAll();
}
}
protected void ebAudiofileSeekerMotionNotifyEvent (object o, MotionNotifyEventArgs args)
{
log.debug("ebAudiofileSeekerMotionNotifyEvent called");
if (Program.getInstance().getAudioManager().Duration > TimeSpan.Zero)
{
int x = -1;
int y = -1;
int intX = -1;
int intY = -1;
int originX;
int originY;
this.GetPosition(out originX, out originY);
Gdk.ModifierType modifierType = Gdk.ModifierType.None;
this.Screen.RootWindow.GetPointer(out x, out y, out modifierType);
this.hsAudiofileSeeker.TranslateCoordinates(this, this.hsAudiofileSeeker.Allocation.X, this.hsAudiofileSeeker.Allocation.Y, out intX, out intY);
double valueAtPos = ((x - (intX + originX)) / (this.hsAudiofileSeeker.Allocation.Width * 1.0)) * this.hsAudiofileSeeker.Adjustment.Upper * 1.0;
log.debug("modifier = " + modifierType);
if (modifierType.HasFlag(Gdk.ModifierType.Button1Mask))
{
log.debug("modifier is button 1, so change value");
this.hsAudiofileSeeker.Value = valueAtPos;
}
long ticksAtPosition = (Program.getInstance().getAudioManager().Duration.Ticks * (long)valueAtPos) / 100;
TimeSpan timeSpanAtPosition = TimeSpan.FromTicks(ticksAtPosition);
this.lblTooltipAudiofileSeeker.Text = (timeSpanAtPosition.Hours > 9 ? timeSpanAtPosition.Hours.ToString() : "0" + timeSpanAtPosition.Hours.ToString()) + ":" + (timeSpanAtPosition.Minutes > 9 ? timeSpanAtPosition.Minutes.ToString() : "0" + timeSpanAtPosition.Minutes.ToString()) + ":" + (timeSpanAtPosition.Seconds > 9 ? timeSpanAtPosition.Seconds.ToString() : "0" + timeSpanAtPosition.Seconds.ToString());
this.hsAudiofileSeeker.TooltipWindow.Move(x, intY + originY);
}
}
protected void ebAudiofileSeekerLeaveNotifyEvent (object o, LeaveNotifyEventArgs args)
{
log.debug("ebAudiofileSeekerLeaveNotifyEvent called");
this.hsAudiofileSeeker.TooltipWindow.HideAll();
}
The code can be found here: http://sourceforge.net/p/audiocuesheet/code/HEAD/tree/

Related

Convert mm (metric) to imperial (fraction) in c#

public class Convert
{
public void MMtofeetfraction(float millimeters)
{
if ((millimeters % 304.8f) != 0)
{
int feet = (int)(millimeters / 304.8f);
double inchWithDecimal = millimeters * 0.03937;
string s = inchWithDecimal.ToString("0.0000");
string[] parts = s.Split('.');
int i1 = int.Parse(parts[0]);
float i2 = float.Parse("0." + parts[1]);
int inch = i1 % 12;
var accuracy = 16;
double num = 1;
double frac = i2 * accuracy;
num = Math.Round(frac);
if (num != 0)
{
while (num % 2 == 0)
{
num = num / 2;
accuracy = accuracy / 2;
}
if (inch != 0)
{
Debug.Log("Fraction output: " + feet + "'-" + inch + " " + num + "/" + accuracy + "\"");
}
else
{
Debug.Log("Fraction output: " + feet + "'-" + num + "/" + accuracy + "\"");
}
}
else
{
Debug.Log("Fraction output: " + feet + "'-" + inch + "\"");
}
}
else
{
Debug.Log("Fraction output: " + Math.Round(millimeters / 304.8) + "'");
}
}
}
Input 1440 : output : 4' 7 1/2"
Input 1550 : output : 5' 1 "
Input 1530 : output : 5' 1/4"
Now, this code works and gives output as needed. I was looking to improvise this code by removing string splitting and other string formatting. Can someone help with inbuilt functions to handle this?

C# Winforms: Returning values to a button event

I'm completely new to C# programming, and I'm trying to make a custom calculator using Windows Forms.
Three text boxes txtMinSkill, txtMaxSkill, txtCooldown should be keyed values into, and clicking a button buttonCalculate should do some calculations and present the result in a label resultLabel.
I have managed to get everything working down to the skill.Display function, but I have no idea how to display the variables hours, minutes, seconds in the label. When I try to access them from within the button event, I just get a message that it does not exist in the current context. And I can't access the label from the Display method.
Can anyone assist? Thanks!
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void buttonCalculate_Click(object sender, EventArgs e)
{
double minSkill;
double maxSkill;
double coolDown;
minSkill = float.Parse(txtMinSkill.Text) * 10;
maxSkill = float.Parse(txtMaxSkill.Text) * 10;
coolDown = float.Parse(txtCooldown.Text);
SkillGainCalculator skill = new SkillGainCalculator();
skill.IntegerMax(maxSkill);
skill.RemainderMax(maxSkill);
skill.RemainderMin(minSkill);
skill.IntegerMin(minSkill);
skill.Calculate(minSkill,maxSkill);
skill.Display(coolDown);
}
}
class SkillGainCalculator
{
//member variables
private int integerMax;
private int remainderMax;
private int integerMin;
private int remainderMin;
private double counter;
const int constant = 6480;
private int i;
private double totalTime;
private int hours;
private int minutes;
private int seconds;
public double IntegerMax(double intMax)
{
integerMax = (int)((1000 - intMax) / 50);
return integerMax;
}
public int RemainderMax(double intMax)
{
remainderMax = (int)((1000 - intMax) % 50);
return remainderMax;
}
public int RemainderMin(double intMin)
{
remainderMin = (int)((1000 - intMin) % 50);
return remainderMin;
}
public int IntegerMin(double intMin)
{
if (remainderMin == 0)
{
integerMin = (int)((1000 - intMin) / 50) - 1;
return integerMin;
}
else
{
integerMin = (int)((1000 - intMin) / 50);
return integerMin;
}
}
public double Calculate(double intMax, double intMin)
{
for (i = integerMax; i <= integerMin; i++)
{
if (i == integerMax && remainderMax != 0)
{
if (intMax <= 700)
{
counter = counter + constant * Math.Pow(0.8, i) * (50 - remainderMax) / 50;
}
else
{
counter = counter + constant * Math.Pow(0.8, i) * (50 - remainderMax) / 50;
}
}
else if (i == integerMin && remainderMin != 0)
{
if (intMin < 700)
{
counter = counter + constant * Math.Pow(0.8, i) * remainderMin / 50;
}
else
{
counter = counter + constant * Math.Pow(0.8, i) * remainderMin / 50;
}
}
else if (i >= 6)
{
counter = counter + constant * Math.Pow(0.8, i);
}
else
{
counter = counter + constant * Math.Pow(0.8, i);
}
}
return counter;
}
public void Display(double clD)
{
totalTime = counter * clD / 3600;
hours = (int)(counter * clD / 3600);
minutes = (int)((totalTime - hours) * 3600 / 60);
seconds = (int)((totalTime - hours) * 3600 % 60);
}
}
I have no idea, what your code does and as #Steve already said your question misses some key infos. Nevertheless try changing your two methods Display and buttonCalculate_Click like this:
public string Display(double clD)
{
totalTime = counter * clD / 3600;
hours = (int)(counter * clD / 3600);
minutes = (int)((totalTime - hours) * 3600 / 60);
seconds = (int)((totalTime - hours) * 3600 % 60);
return "Hours: " + hours + ", Minutes: " + minutes + ", Seconds: " + seconds;
}
private void buttonCalculate_Click(object sender, EventArgs e)
{
double minSkill;
double maxSkill;
double coolDown;
minSkill = float.Parse(txtMinSkill.Text) * 10;
maxSkill = float.Parse(txtMaxSkill.Text) * 10;
coolDown = float.Parse(txtCooldown.Text);
SkillGainCalculator skill = new SkillGainCalculator();
skill.IntegerMax(maxSkill);
skill.RemainderMax(maxSkill);
skill.RemainderMin(minSkill);
skill.IntegerMin(minSkill);
skill.Calculate(minSkill, maxSkill);
resultLabel.Text = skill.Display(coolDown);
}
The method Display now generates the string you want to display and returns it when called so you can set resultLabel.Text from you calling method:

Write getter for Seconds of Fast Days

I have a function called getDayTimeParameter(), which gets the day parameter from 0 to 1. I also have two functions which are getters of hour and minute. I need to show time as hh:mm:ss. But the problem is I have no idea how to write getter for seconds. Thanks in advance!
public float getDayTimeParameter()
{
return System.DateTime.Now.Minute / 60f + System.DateTime.Now.Second / 3600f + System.DateTime.Now.Millisecond / 3600000f;
}
public int getHour()
{
int dayMinute = Mathf.RoundToInt(24 * 60 * getDayTimeParameter());
return Mathf.FloorToInt(dayMinute / 60f);
}
public int getMinute()
{
int dayMinute = Mathf.RoundToInt(24 * 60 * getDayTimeParameter());
int hour = getHour();
return Mathf.FloorToInt((dayMinute / 60f - hour) * 60f);
}
public int getSecond()
{
// What to do in here?
}
public string getFullTimeString()
{
int hour = getHour();
int minute = getMinute();
int second = getSecond();
string minutesString;
if (minute < 10)
{
minutesString = "0" + minute;
}
else {
minutesString = "" + minute;
}
string hoursString;
if (hour < 10)
{
hoursString = "0" + hour;
}
else
{
hoursString = "" + hour;
}
string secondsString;
if (second < 10)
{
secondsString = "0" + second;
}
else
{
secondsString = "" + second;
}
return hoursString + ":" + minutesString + ":" + secondsString;
}
Given that your getDayTimeParameter function returns 0-1, and a full day equals 1
then the following should give you accurate Hours, Minutes and Seconds.
public int getHour()
{
return Mathf.FloorToInt(getDayTimeParameter() * 24);
}
public int getMinute()
{
var hourSubtraction = getHour() * 60;
return Mathf.FloorToInt((getDayTimeParameter() * 1440) - hourSubtraction);
}
public int getSecond()
{
var hourSubtraction = getHour() * 3600;
var minuteSubtraction = getMinute() * 60;
return Mathf.FloorToInt((getDayTimeParameter() * 86400) - hourSubtraction - minuteSubtraction);
}
can't you just use DateTime.Now.ToString("hh:mm:ss") with its various options if necessary

Heightmap Generation using Perlin Noise returns black bitmap

i'm making a Heightmap Generator using Perlin Noise, as the title says.
i've used a pseudocode from this site -> http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
and turned in to C# code. so far i've done all the variable type assignment and the code gives an output. unfortunately my output looks like this ->
as you can see, the right and bottom edges have a slight gradiant from black to white, but everything else is black.
here is my c# source ->
private void button1_Click( object sender, EventArgs e ) {
persistence = float.Parse( textBox4.Text );
NumberOfOctaves = Int32.Parse( textBox5.Text );
int width = Int32.Parse( textBox1.Text );
int height = Int32.Parse( textBox2.Text );
float zoom = float.Parse( textBox3.Text );
generate( width, height, zoom );
}
public float Noise( int x, int y ) {
long n = x + ( y * 57 );
n = ( long )Math.Pow( ( n << 13 ), n );
return ( float )( 1.0 - ( ( n * ( n * n * 15731 + 789221 ) + 1376312589 ) & 0x7fffffff ) / 1073741824.0 );
}
public float SmoothNoise( float x, float y ) {
float corners = ( Noise((int) (x-1), (int) (y-1)) + Noise((int) (x+1), (int) (y-1)) + Noise((int) (x-1), (int) (y+1)) + Noise((int) (x+1), (int) (y+1)) ) / 16;
float sides = ( Noise((int) (x-1), (int) y) + Noise((int) (x+1), (int) y) + Noise((int) x, (int) (y-1)) + Noise((int) x, (int) (y+1)) ) / 8 ;
float center = Noise( (int)x, (int)y ) / 4;
return corners + sides + center;
}
public float CosineInterpolate( float a, float b, float x ) {
double ft = x * 3.1415927;
double f = ( 1 - Math.Cos( ft ) ) * 0.5;
return (float)( ( a * ( 1 - f ) ) + (b * f) );
}
public float InterpolatedNoise( float x, float y ) {
// MessageBox.Show( x.ToString() );
int intX = ( int )x;
float fractX = x - intX;
int intY = ( int ) y;
float fractY = y - intY;
float v1 = SmoothNoise(intX, intY);
float v2 = SmoothNoise(intX + 1, intY);
float v3 = SmoothNoise(intX, intY + 1);
float v4 = SmoothNoise(intX + 1, intY + 1);
float i1 = CosineInterpolate(v1 , v2 , fractX);
float i2 = CosineInterpolate(v3 , v4 , fractX);
// MessageBox.Show( intX + "\n" + intY + "\n" + fractX + "\n" + fractY + "\n" + v1 + "\n" + v2 + "\n" + v3 + "\n" + v4 + "\n" + i1 + "\n" + i2 + "\n" + CosineInterpolate( i1, i2, fractY ) );
return CosineInterpolate(i1 , i2 , fractY);
}
public float PerlinNoise2D( float x, float y ) {
float total = 0;
float p = persistence;
int n = NumberOfOctaves;
for(int i = 0; i < n; i++ ) {
int frequency = (int)Math.Pow( 2, i );
// MessageBox.Show( Math.Pow( 2, i ).ToString() );
float amplitude = ( int )Math.Pow( p, i );
total = total + InterpolatedNoise(x * frequency, y * frequency) * amplitude;
}
return total;
}
private void generate( int sizeX, int sizeY, float zoom ) {
int zoomX = (int)( sizeX * zoom );
int zoomY = (int)( sizeY * zoom );
float max = int.MinValue;
float min = int.MaxValue;
float[,] nmap = new float[zoomX,zoomY];
Bitmap heightMap = new Bitmap(zoomX,zoomY);
for (int x=0; x<zoomX; x++) {
for (int y=0; y<zoomY; y++) {
// MessageBox.Show( PerlinNoise2D( x / zoom, y / zoom ).ToString() );
nmap[x,y] = PerlinNoise2D(x/zoom,y/zoom);
max = (max < nmap[x,y]) ? nmap[x,y] : max;
min = (min > nmap[x,y]) ? nmap[x,y] : min;
}
}
max = max-min;
for (int x=0; x<zoomX;x++) {
for (int y=0; y<zoomY;y++) {
int calc = (int) ( (nmap[x,y] - min) / max );
heightMap.SetPixel(x,y,Color.FromArgb(calc,calc,calc));
}
}
pictureBox1.Image = heightMap;
}
also i could upload the visual studio solution in a zip if anyone want's to.
so far now i've found out that something is wrong with the Noise() function, because it returns -0,281... the most time. it should return floating point numbers between -1.0 and 1.0.
i've tryed it with other random functions, but the output ooks the same every time.
i hope you guys can help me out, and thx for anny suggestions.
I have found two issues in code.
First, you incorrectly interpreted ^ symbol as a power function
in original source code, while it is a xor operation. So line
n = ( long )Math.Pow( ( n << 13 ), n );
Should be
n = ( long )(( n << 13 ) ^ n);
Second, when creating color pixel from noise value, your noise is in range 0..1, and color value should be in range 0..255, so line
int calc = (int) ( (nmap[x,y] - min) / max );
Should be
int calc = (int) (( (nmap[x,y] - min) / max ) * 255);
Full working (console) sample here: http://ideone.com/RGVf8J

How can I solve the Collatz conjecture algorithm in C#?

I was able to solve the Collatz conjecture algorithm (no, i didn't try to prove it) in about 5 minutes using Java.
Now that I'm learning C# to make web apps, I'm running into trouble doing the same thing.
I simply want the user to enter a number, click a button, and print the output to a text box.
Here is the button Click event handler method I'm using:
protected void Button3_Click(object sender, EventArgs e)
{
string x = TextBox1.Text; //user entered a number
string y =collatz(x); //this function is below and returns a string
chatbox.Text = y; //output
}
And here is the Collatz method:
public static string collatz(string y)
{
if (y == null)
return null;
double x = double.Parse(y); //x is my "n"
y = x.ToString(); //output string
double large = x; //keep track of biggest number
// the algorithm
// the redundancies (like x==1.. x!= 1) are part of troubleshooting :/
while (x > 1)
{
if (x % 2 == 0)
{
x = x / 2;
if (x > large)
large = x;
if (x != 1)
y = y+" "+ x.ToString();
if (x == 1)
{
y = y + " " + x.ToString();
y = y + " largest number was " + large;
}
}
if (x % 2 != 0)
{
if (x == 1)
{
y = y+" "+ x.ToString();
y = y + " largest number was " + large;
}
x = (3 * x) + 1;
if (x > large)
large = x;
y = y+" "+ x.ToString();
}
}
return y;
}
EDIT
when I use the VS.net debugger and enter a number like 2, I get NO output and NO error. I'm just left waiting forever. If it were an infinite loop, I would get an error eventually, right?
and no, this is not a homework problem (it was 2 years ago when I did it in JAVA though :).) I'm learning C# independently.
You had an infinite loop. Try this:
public static string collatz(string y)
{
if (y == null)
{
return null;
}
int x = int.Parse(y); //x is my "n"
var results = new StringBuilder();
results.Append(x.ToString());
int largest = x; //keep track of biggest number
// the algorithm
// the redundancies (like x==1.. x!= 1) are part of troubleshooting :/
while (x > 1)
{
if (x % 2 == 0)
{
x = x / 2;
if (x > largest)
{
largest = x;
}
if (x != 1)
{
results.Append(" " + x.ToString());
}
if (x == 1)
{
results.Append(" " + x.ToString());
results.Append(" largest number was " + largest.ToString());
return results.ToString();
}
}
if (x % 2 != 0)
{
if (x == 1)
{
results.Append(" " + x.ToString());
results.Append(" largest number was " + largest.ToString());
return results.ToString();
}
x = (3 * x) + 1;
if (x > largest)
{
largest = x;
}
results.Append(" " + x.ToString());
}
}
return results.ToString();
}
Two notes:
When you're doing string concatenation in a loop, it's a good habit to use a StringBuilder rather than s = s + t. Lots, lots less memory allocations.
A lot of times you can't rely on == when it comes to double values. It seems to work in this case, but it might not when you get to higher numbers where there's less precision. Since all the numbers are going to be int's anyway, might as well use those.
if (x == 1)
{
y = y+" "+ x.ToString();
y = y + " largest number was " + large;
}
This part here (odd x) is redundant. For if x is 1, it will never enter the while loop. Your code seems logically. Maybe try using integer instead.
x = x / 2;
if (x > large)
large = x;
Redundant code again for even x part. How do you expect x to be bigger than large after division by 2? Just check it in the 3n+1 part will do.
if (x == 1)
{
y = y + " " + x.ToString();
y = y + " largest number was " + large;
}
You can just leave this part out and let the while loop handle this check.
public static string collatz(string y)
{
if (y == null)
return null;
double x = double.Parse(y);
y = x.ToString();
double large = x;
while (x > 1) {
if (x % 2 == 0) {
x = x / 2; // x reassigned
if (x > large)
large = x;
if (x != 1)
y = y + " " + x.ToString();
if (x == 1) {
y = y + " " + x.ToString();
y = y + " largest number was " + large;
}
}
// Infinite loop goes because of that
if (x % 2 != 0) { // double check on reassigned variable, use “else” instead
if (x == 1) {
y = y + " " + x.ToString();
y = y + " largest number was " + large;
}
x = (3 * x) + 1;
if (x > large)
large = x;
y = y + " " + x.ToString();
}
}
return y;
}
I tried it with fixed code (using else) and it works fine.
Also, you don't need double type since Collatz works with natural numbers. The following is a quick refactoring to add more .NET-ty to your code:
public static string collatz(string input)
{
int current = 0;
if (string.IsNullOrEmpty(input) || !int.TryParse(input, out current) || current < 1) {
return "Empty, not a number or less then 1";
}
int max = current;
while (current > 1) {
if (current % 2 == 0) {
current = current / 2; // current reassigned
if (current > max)
max = current;
if (current != 1)
input = input + " " + current.ToString();
if (current == 1) {
input = input + " " + current.ToString();
input = input + " largest number was " + max;
}
} else {
if (current == 1) {
input = input + " " + current.ToString();
input = input + " largest number was " + max;
}
current = (3 * current) + 1;
if (current > max)
max = current;
input = input + " " + current.ToString();
}
}
return input;
}
View Equation:
if the number is even: n/2
if the number is odd: 3n+1
Step One:
Add a method called Collazt which returns a collection of objects of type int of class List<?>
public static List<int> Collazt(int n) {
List<int> data = new List<int>();
data.Add(n);
int resul = 0;
while (true) {
if (n == 1) {
break;
}
if ((n % 2) == 0)
{
resul = n / 2;
n = resul;
}
else {
resul = (n * 3) + 1;
n = resul;
}
data.Add(n);
}
return data;
}
Step Two:
We call the method in our main class.
static void Main(string[] args)
{
Console.Write("N: ");
int r = int.Parse(Console.ReadLine());
List<int> result = Collazt(r);
Console.WriteLine("Lista:");
Console.WriteLine("[");
for (int i= 0; i<result.Count; i++) {
Console.Write(result[i]+"\n");
}
Console.WriteLine("]");
}
string restart;
do
{
Console.WriteLine("Type a Whole Number");
double n = Convert.ToDouble(Console.ReadLine());
do
{double a = n;
if (n % 2 == 0)
{
Console.WriteLine("Even");
n = a / 2;
Console.WriteLine(n);
}
else
{
Console.WriteLine("Odd");
n = (3*a) + 1;
Console.WriteLine(n);
}
}
while (n != 1);
Console.WriteLine("Yo Wanna Restart? Type y and press enter");
restart = Console.ReadLine();
Console.Clear();
}
while (restart == "y");
Console.ReadKey(true);
(not a professional programmer, made it for fun, i know there are better ways)

Categories

Resources