Descending Numbers C# - c#

I was able to write this tiny segment of this program to display the numbers in Ascending order but i still cant get it to display it in Descending order.
Basics of what this program should do is takes in two number values from the user in the form of "From" and "To" and displays it as a list in the listbox. The users choice of either ascending or descending order depends on which of the two Radio buttons he has selected.
private void btnCalc_Click(object sender, EventArgs e)
{
double fromNum, toNum, total = 0;
fromNum = double.Parse(txtFrom.Text);
toNum = double.Parse(txtTo.Text);
lstResult.Items.Clear();
lblResult.Text = "";
if (radAsc.Checked)
{
while (fromNum <= toNum)
{
lstResult.Items.Add(fromNum);
total = total + fromNum;
fromNum++;
}
}
else
{
while (fromNum >= toNum)
{
lstResult.Items.Add(fromNum);
total = total + toNum;
toNum--;
}
}
lblResult.Text = total.ToString();
}
Here's an image to what the program looks like.
http://imgur.com/SVwN3Tx
Note:- I am completely new to C# and I've just started taking it in College.

I suggest using for loop instead of while which makes the code easy to implement:
if (radAsc.Checked)
{
// num += 1: - I've seen odds/even switch on the screenshot
// so you may want to change/add num += 1 into num += 2
for (double num = fromNum; num <= toNum; num += 1) {
lstResult.Items.Add(num);
total = total + num;
}
}
else
{
// Descending order:
// - start from the bottom (toNum)
// - loop until the top (fromNum)
// - descend by 1 (num -= 1)
for (double num = toNum; num >= fromNum; num -= 1) {
lstResult.Items.Add(num);
total = total + num;
}
}

You're decrementing the wrong value
while (fromNum >= toNum)
{
lstResult.Items.Add(fromNum);
total = total + toNum;
toNum--;
}
So, here's what you're doing:
Say fromNum is 10, and toNum is 1.
After your first iteration, fromNum is still 10 but toNum is 0. Decrement the fromNum instead of toNum and it should work accordingly.
EDIT
Couple things to take note. If total is collecting the sum of all numbers, a neat way to write:
total = total + value;
is
total += value;.
You should also verify that the numbers will actually work before going into your logic. So if the radio button is selected for Ascending order, you want to make sure fromNum is less than toNum, and maybe throw up a message box if they're not:
if(fromNum < toNum)
{ run logic .... }
else
{ alert user ... }

Related

What should I do in order to display how many loops it takes to get a favourable number?

Im new to programming and Im currently attempting to make a dice program, where the user can input how many throws they would like to do and then a list will display how many throws it took to get a specific number, in this case that number is 6 (later on I'd like to make it for all numbers 1-6) How should I go about doing this?
Im currently trying to use an if-statement to recognize when a specific number is rolled, currently I want the program to recognize the number 6, but im a bit unsure how to display the amount of rolls it took to get that number, in a list, and also keeping the loop going until all rolls have been executed.
private void Btnkast_Click(object sender, EventArgs e)
{
bool throws;
int numberofthrows = 0;
int dice;
Random dicethrow = new Random();
throws = int.TryParse(rtbantal.Text, out numberofthrows);
int[] list = new int[numberofthrows];
for (int i = 0; i <= numberofthrows; i++)
{
dice = dicethrow.Next(1, 7);
if (dice == 6)
{...}
}
}
Also, the only reason I use tryparse is to prevent crashes when having to handle with string-values.
I have written this for you using a C# Console Application, but I'm sure you will be able to edit it to fit your requirements for Windows Forms.
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
Random rnd = new Random(); // create Random object
Console.WriteLine("Enter a number between 1 and 6: "); // prompt user to enter a number between 1 and 6
int chosenNumberInt;
var chosenNumber = int.TryParse(Console.ReadLine(), out chosenNumberInt); // check to see if user actually entered a number. If so, put that number into the chosenNumberInt variable
Console.WriteLine("How many rolls would you like?"); // prompt user to enter how many rolls they would like to have
int chosenRollsInt;
var chosenRolls = int.TryParse(Console.ReadLine(), out chosenRollsInt);
Console.WriteLine(); // to create space
Console.WriteLine(); // to create space
Console.WriteLine("Chosen Number = " + chosenNumberInt + " --- Chosen Rolls = " + chosenRollsInt); // show user what they entered
Console.WriteLine("------------");
int count = 0;
int numberRolled = 0;
var lstRolls = new List<int>(); // create list object
for(int i = 1; i <= chosenRollsInt; i++)
{
count++;
int dice = rnd.Next(1, 7);
numberRolled = dice;
lstRolls.Add(numberRolled); // add each roll to the list
Console.WriteLine("Roll " + i + " = " + numberRolled); // show each roll
}
var attempts = lstRolls.Count; // how many rolls did you do
var firstIndexOfChosenNumber = lstRolls.FindIndex(x => x == chosenNumberInt) + 1; // have to add 1 because finding the index is 0-based
Console.WriteLine("-------------");
if(firstIndexOfChosenNumber == 0)
Console.WriteLine("The chosen number was " + chosenNumberInt + " and that number was NEVER rolled with " + chosenRollsInt + " rolls.");
else
Console.WriteLine("The chosen number was " + chosenNumberInt + " and the number of rolls it took to hit that number was " + firstIndexOfChosenNumber);
}
}
Something that I didn't add would be the validation to ensure that the user does indeed enter a number between 1 and 6, but you can do that I'm sure.
I have created a DotNetFiddle that proves this code does work and even shows you each roll.
Let me know if this helps or if you need any more assistance.
UPDATE
Based on your comment on my original post, I have edited my code to allow the user to enter the number they want, along with how many rolls. Then, once all of the rolls have been completed, I find the index of the first occurrence of the number they selected in the beginning.
Let me know if this is what you want.
Read the comments I added in the code
private void Btnkast_Click(object sender, EventArgs e)
{
bool throws;
int numberofthrows = 0;
int dice;
Random dicethrow = new Random();
throws = int.TryParse(rtbantal.Text, out numberofthrows);
List<int> list = new List<int>(); //I changed this to a list
for (int i = 0; i < numberofthrows; i++)
{
dice = dicethrow.Next(1, 7);
list.Add(dice); //add every roll to the array to check later the values if you want
if (dice == 6)
{
//Print that you found 6 at the roll number list.Count
Console.WriteLine("Found 6 at roll number: " + list.Count);
break; //probably break the loop so you won't continue doing useless computation
}
}
}

Random Integer, no repeat, within specific range

Detailed scenario:
There are 300 possible numbers that fit into the discription.
That is, the number must between 1123 and 5543 inclusive
The number is unique and not repeated
The number only has the integers 1,2,3,4 and 5.
What I am trying to achieve is a program that can display all those numbers at once in ascending order.
My current code:
var chars = "12345";
var stringChars = new char[4];
var random = new Random();
for (int i = 0; i < stringChars.Length; i++)
{
stringChars[i] = chars[random.Next(chars.Length)];
}
var finalString = new String(stringChars);
Console.WriteLine(finalString)
This code works fine, but I have 2 additional requirements.
Loop 300 times
Display all results in ascending order
EDIT:
Sorry for all confusion. What this code produces is a 4 digit number like I want. But I want to it to do so 300 times. I guess I can use a Loop, but this is my first time using C# (I've only used vb.net in the past). What I mean by random and in ascending order is: Produce a random number, and when all numbers are generated, order them in ascending order before displaying them all.
However, if ordering them will be too complicated, then I'm fine without that.
It's not entirely clear what you're asking, but here is some code that will print the 611 (not 300) numbers matching the description you gave in ascending order.
If I've understood your question correctly, you will want to sample 300 distinct elements from this larger set, sort them, and them print them out. You might look at using a Fisher-Yates shuffle to do this. Shuffle the list, take the first 300, and sort them.
public static void Main (string[] args) {
var digits = new [] { 1, 1, 2, 3 };
for (var num = DigitsToInt(digits); num <= 5543; num = DigitsToInt(digits)) {
Console.WriteLine(num);
for (int i = 3; i >= 0; i--) {
digits[i]++;
if (digits[i] < 6) {
break;
} else {
digits[i] = 1;
}
}
}
}
private static int DigitsToInt(int[] digits) {
return 1000 * digits[0] + 100 * digits[1] + 10 * digits[2] + digits[3];
}

Operation on two List<>

I am stuck with this for quite a while. What I want my program to do :
I will have two lists. One of quantity and one of price. I want to multiply two according to their serial(example : quantity[i] * price[i]) and add the multiplication result together and get a specific number lets say I add them and I get 100 but I want 101.123 and the way I want to achieve is adding 0.001 to the first price number (I cant touch the quantity number) and check if it matches the answer I wanted. I cant add more than 5 so if it fails to get the number from the first number I want to move to the second one and leave the first one as it was before. Any one? Here's where i have gotten.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ultimateproject_beginner_ {
class Program {
static List<decimal> QuantityList() {
Console.WriteLine("Quantity");
Console.WriteLine();
List<decimal> quantityList = new List<decimal>();
for (;;) {
string stringQuantityNumber = Console.ReadLine();
decimal quantityNumber = 0M;
if (stringQuantityNumber == "done") {
break;
} else {
if (decimal.TryParse(stringQuantityNumber, out quantityNumber)) {
quantityList.Add(quantityNumber);
}
}
}//end of for loop
return quantityList;
}
static List<decimal> PriceList() {
Console.WriteLine("Price");
List<decimal> priceList = new List<decimal>();
for (;;) {
string stringPriceNumber = Console.ReadLine();
decimal priceNumber = 0M;
if (stringPriceNumber == "done") {
break;
} else {
if (decimal.TryParse(stringPriceNumber, out priceNumber)) {
priceList.Add(priceNumber);
}
}
}//end of for loop
return priceList;
}
static void Main(string[] args) {
List<decimal> quantityList = QuantityList();
List<decimal> priceList = PriceList();
decimal destination = 101.123M;
decimal sum = 0M;
for (int i = 0; i < quantityList.Count; i++) {
decimal product = priceList[i] * quantityList[i];
sum = sum + product;
}
Console.ReadKey(true);
}
}
}
I have tried to make it work with some nested for loops but I get stuck where I have to multiply the new value with all other ones.
What I get: 100, What I want : 101.123 How: by adding 0.001 to priceList and check if the sum is 101.123
One approach to dealing with this is to compute the total on first path, then figure out how many additions you would need, and then perform the adjustments. Note that it is possible that you wouldn't be able to reach the desired target, because the max value that you can add is limited by $0.05 times the total quantity of all items ordered. If the sum is $100, you need $101.23, but the order has only ten items in all, the highest you can get with $0.04 per item is $100.50.
You can compute the total using LINQ:
var total = quantityList.Zip(priceList, (q, p) => q*p).Sum();
Compute the value remaining to be assigned, and go through the individual rows, and do the adjustment until remaining drops to zero:
var remaining = destination - total;
for (int i = 0; remaining > 0 && i < quantityList.Count; i++) {
var quantity = quantityList[i];
// Avoid crashes on zero quantity
if (quantity == 0) {
continue;
}
// We cannot assign more than quantity * 0.05
var toAssign = Math.Min(remaining, quantity * 0.05);
remaining -= toAssign;
// Split the amount being assigned among the items
priceList[i] += toAssign / quantity;
}
if (remaining > 0) {
Console.WriteLine("Unable to distribute {0:C}", remaining);
}
Note: Ideally, you should consider creating a class representing quantity/price pairs, rather than using parallel lists.
After sum is calculated, compare it to destination. If sum < destination, then calculate number of 0.001 increments needed as count = (destination - sum) / 0.001. If this is less than 5, then add this many to the first price, otherwise add five of them (0.005), and then subtract 5 from count. If count > 0 then repeat the process for the second price, etc. If count is greater than pricelist.Count * 5, you can't reach the destination price.

Detecting spikes and drops in a long list of integers C#

Hi there I'm trying to write a method that reads every number in a list and detects where it spikes and drops. This is what I have so far:
I basically figure if I loop through the list, loop through it again to get the next number in the list, then detecting if it's more or less. If it's more it'll save to one list, vice versa.
What I want this method to do is determine where there's a spike of 100 or more, save the point that it does this (which is 'counter') and also save the points where the numbers drop.
This so far notices only a drop and it will save every number in the list until it spikes again and once it has spiked it shows no numbers, until it drops again and so on.
I've put 'check' and 'check2' to try and counteract it saving every number after it notices a drop and only save it once but no luck.
Any ideas?
public void intervalDetection()
{
//Counter is the point in the list
int counter = 0;
int spike = 0;
int drop = 0;
//Loop through power list
for (int i = 0; i < powerList.Count(); i++)
{
counter++;
int firstNumber = powerList[i];
//Loop again to get the number after??
for (int j = 1; j < 2; j++)
{
//Detect Spike
spike = firstNumber + 100;
drop = firstNumber - 100;
if (powerList[j] > spike)
{
if (check2 == false)
{
intervalStartList.Add(counter);
check2 = true;
check = false;
}
}
//Detect Drop
else if (powerList[j] < drop)
{
if (check == false)
{
intervalEndList.Add(counter);
check = true;
check2 = false;
}
}
}
Create integer "average"
Loop through List/Array and add each value to average
Divide average by the count of the List/Array
Loop through List/Array and check deviation to the average integer
derp
Code example:
public class DSDetector {
public static List<int>[] getDropsnSpikes(List<int> values, int deviation) {
List<int> drops = new List<int>();
List<int> spikes = new List<int>();
int average = 0;
foreach (int val in values) {
average += val;
}
average = average/values.Count;
foreach (int val in values) {
if (val < average - deviation) {
drops.add(val);
}
if (val > average + deviation) {
spikes.add(val);
}
}
//derp.
return new List<int>{drops, spikes};
}
}
not tested but I think it works. Just try it.
What exactly do you mean saying "peaks" and "drops"?
Let's say you have following list of integers
112, 111, 113, 250, 112, 111, 1, 113
In this case value 250 is peak and 1 drop relative to average value and you can get it using Kai_Jan_57 answer.
But also 250 is peak to previous value 113 and 112 is drop for 250.
If you want to find local peaks and drops you can check each value relative to previous and next: find average as avg=(val[i-1]+val[i+1])/2 and check if val[i]>avg + 100 (peak) or val[i]

How to count multiple items in SteamBot

In Jassecar's SteamBot, is there a way to count items of different defindexes and add them up?
I tried this:
switch(message.ToLower())
{
case "ticket":
foreach (ulong id in Trade.OtherOfferedItems)
{
int totalScrap = 0;
Trade.SendMessage("Please pay 3.44 ref");
var items = Trade.OtherOfferedItems;
var itemType = Trade.OtherInventory.GetItem(id);
if (itemType.Defindex == 5002)
{
totalScrap = items.Count * 9;
}
else if (itemType.Defindex == 5001)
{
totalScrap = items.Count * 3;
}
else if (itemType.Defindex == 5000)
{
totalScrap = items.Count;
}
Trade.RemoveAllItems();
if (totalScrap > 31)
{
Trade.AddItemByDefindex(725);
int Change = 31 - totalScrap;
while(Change > 0)
{
Trade.AddItemByDefindex(5000);
Change - 1;
}
}
else
{
Trade.SendMessage("You have only added a total of " + totalScrap + " Scrap, please put up the correct amount and type ticket again");
}
}
break;
But it will count 1 Scrap (item Defindex of 5000) and 1 Refined Metal (item Defindex of 5002) as both 9 and say to the user he has added a total of 18 scrap where he as only added 10. (1 refined = 9 Scrap)
You're iterating over id's in Trade.OtherOfferedItems.
Error#1
On every iteration of the loop you're clearing totalScrap, by setting it to 0.
Error#2
In here:
`totalScrap = items.Count * 9`
you're saying "the total amount of scrap is the ammount of my items multiplied by 9" which is wrong, because if you've got 2 items with possibly different Defindexes (5002 and 5000 in your case), it gives you 18.
Error#3
Then you've got:
Trade.RemoveAllItems();
which I suppose will remove all the items from the collection you're actually iterating over - I'm really amazed that your loop doesn't crash.
Put the totalScrap outside. Iterate over every item and THEN do all the clearing, removing and checking whether the sum is>31 or not.

Categories

Resources