I have a file with data in the form of strings that are sequentially entered into the console. I also have a file of correct answers in the same format. (You may have seen such a testing format on codeforces). I decided to automate the process (in my project in visual studio) and I want to do it through Unit tests so as not to rebuild the code too much every time (so that it passes on codeforces).
Input data in the same format (output the same):
5
256 42
1000 1000
-1000 1000
-1000 1000
20 22
At the moment I have created methods to get the data and compare my results with the correct output file results. But I don't really like this option, since files need to be entered by hand or sorted with a check for existence. I would like these issues to be solved out of the box.
public static string[] GetFileData(string File)
{
string[] result = { };
foreach (string line in System.IO.File.ReadLines(File))
{
string? str = line;
if (str == null) break;
//Console.WriteLine(str);
result.Append(str);
}
return result;
}
public static bool Compare(string[] result, string[] _out)
{
if (result.Length != _out.Length)
{
Console.WriteLine("Error. Array not equal");
return false;
}
for (int i = 0; i < result.Length; i++)
{
if (result[i] != _out[i])
{
Console.WriteLine($"Error! - {result[i]} != {_out[i]}");
return false;
}
}
Console.WriteLine($"Success");
return true;
}
Related
I'd like to create a short program to download several pictures from a website.
On a form, I would like to enter a root-link to a website with placeholders.
The placeholders can be defined with Start/End value and asc/desc.
For example: the original link is
google.de/1236-01.jpg
and I'd like to generate all links from
google.de/1236-1.jpg
up to
google.de/9955-12.jpg
So my input would be "google.de/[0]-[1].jpg" and placeholders are set to:
[0] = start 1236|end 9955|asc
[1] = start 1|end 12|asc
Via GetValidCharacters() I get a String-List of valid combinations for each entered placeholder (can be selected via ascending/descending + start&end).
The goal I'm struggling with is to build all combinations of this link, because I need to determine while runtime, how much placeholders I have.
My idea was to loop over an queue and enquueue each new build line, until there is none left with placeholders, but I don't know how to do this.
I need to make sure that all combinations are entered and they are entered only once.
private static void CreateDownloadList()
{
Queue<string> tmpQueue = new Queue<string>(); //temp queue
tmpQueue.Enqueue(DL_path); //DL_Path = google.de/[0]-[1].jpg
string line = "";
while ((line = tmpQueue.Dequeue()) != null) //not empty
{
if (line.Contains("[")) //placeholder
{
string tmpLine = line;
//how to determine, which placeholder is next?? need to know this and replace this with every combination, I get from GetValidCharacters(start, end, DESC)
}
else //done
{
_urlList.Add(line);
}
}
}
how about a simple for loop?
for (int i = 1236; i <= 9955; i++)
{
for (int j = 1; j <= 12; j++)
{
tmpQueue.Enqueue(string.Format("google.de/{0}-{1}.jpg", i, j));
}
}
I'm not going give you the full code but here is some pseudo code that would solve the problem.
given :
todostack -- stack object that holds a list of unresolved items
replace_map -- map object that holds marker string and map of all values
marker_list -- list of all markers
final_list -- list object that holds the results
(note you can probably use marker_list and replace_map in one object -- I have them separate to make my code clearer)
init :
push todostack with your starting string
set marker_list and replace_map to correct values (from parameters I assume)
clear final_list
algorithm :
while (there are any items in todostack)
{
curitem = todostack.pop
if (curitem contains a marker in marker_list)
{
loop for each replacement in replace_map
{
new_item = curitem replaced with replacement
todostack.push(new_item)
}
}
else
add curitem to final_list
}
#Hogan this was the hint to the correct way.
solution is this
private void CreateDownloadList()
{
Queue<string> tmpQueue = new Queue<string>();
tmpQueue.Enqueue(downloadPathWithPlaceHolders);
while(tmpQueue.Count > 0)
{
string currentItem = tmpQueue.Dequeue();
bool test = false;
if(currentItem.Contains("["))
{
foreach(Placeholder p in _placeholders)
{
if(currentItem.Contains(p.PlaceHolder))
{
foreach(string s in p.Replacements)
{
tmpQueue.Enqueue(currentItem.Replace(p.PlaceHolder, s));
}
test = true;
}
if(test)
break;
}
}
else
{
_downloadLinkList.Add(currentItem);
}
}
}
public class call
{
DateTime time = DateTime.Now;
public void check()
{
int count=0;
if(time < time.AddSeconds(30))
{
count ++;
if(count == 5)
{
Console.WriteLine(count);
}
}
public class Program
{
public static void Main(string[] args)
{
int input;
string sinput;
call one = new call();
call two = new call();
sinput = Console.ReadLine();
input = int.Parse(sinput);
do{
switch(input)
case 1: one.check();
break;
case 2: two.check();
break;
default: Console.WriteLine(":::");
break;
}while(input > 9)
}
}
}
I am new to programming...
I tried to print the number If it occurred 5 time within 30 sec...
I give input 1 to 9.. if the same input occurred 5 times with in 30 sec I want to print that..
You have a few bugs:
You'll probably want to replace:
if(time < time.AddSeconds(30))
With something the compares to the current time such as:
if(DateTime.Now < time.AddSeconds(30))
You are also incrementing count twice in your check method, not sure if that was intentional.
Inside of your do loop your switch body needs to be inside of {} and you probably should be reading a new input each time or doing something else to change the input or your loop will run forever.
You should also always validate user input. In this case if someone enters something other than a number your application will crash form this code:
sinput = Console.ReadLine();
input = int.Parse(sinput);
Instead lookup the int.TryParse method.
You create something like a class that logs the data for a certain input value (that is, stores the dates at which they are entered) and a class that binds those. Like, in pseudo-code:
class SingleInputLogger {
List<Date> dates
void addDate(Date date){
push date in dates
}
unsigned int currentSize(){
remove all entries from dates which are too old
return size of dates
}
}
class InputLogger {
Array<SingleInputLogger> singleInputLoggers of size 10 (or 9 if only 1..9, but then mind the offset)
//adds an input and also returns true if the input has a count of more than five
void addInput(int input){
singleInputLoggers[input].addDate(currentTime())
}
bool checkInput(int input){
if(singleInputLoggers[input].currentSize() >= 5){
return true
}
return false
}
Then the main routine becomes
InputLogger logger
while(get input){
logger.addInput(input)
if(logger.checkInput(input)){
display message "input " + input + " was entered more than five times in 30s"
}
}
(List was used to indicate a linked list in order to be able to efficiently remove front entries, Array was used to indicate a structure of static size for fast access)
Remember to let classes like this do the job for you. Try to use as less functions as possible and rather go with methods.
If someone has better names for those classes (I admit that my names are not that great), feel free to edit my answer.
I have a text file that contains:
Memory Test
Test Results : Pass
Video Test
Test Results : Pass
Audio Test
Test Results : Fail
I need to return 'true' if all Test Results are Pass and 'false' if one or more test results is Fail.
List<string> filecontents = File.ReadAllLines("abc.txt").ToList<string();
//If all "Test results : Pass"
{
return true;
}
for (int i = 0; i < filecontents.Count; i++)
{
if (filecontents[i].Contains("Test Results : Fail"))
{
return false;
}
}
Thank you.
You already got it,
....
for (int i = 0; i < filecontents.Count; i++)
{
if (filecontents[i].Contains("Test Results : Fail"))
{
return false;
}
}
return true;
No need to read the entire file into memory at once:
var oneOrMoreTestsFailed =
File.ReadLines(filename)
.Any(x => x.Contains("Test Results : Fail"));
return !oneOrMoreTestsFailed;
This reads the file line-by-line. It also will exit when it encounters the first failure. So it doesn't necessarily have to read the entire file.
It sounds like you are really just looking for the presence of "Fail" right?
string text = File.ReadAllText("myText.txt");
if (text.Contains("Fail"))
return false;
I have this code to validate a phone number but it looks a bit awkward. I'm guessing theres a better way to go about this. How can I make this more efficient?
public static bool validTelephoneNo(string telNo)
{
bool condition = false;
while (condition == false)
{
Console.WriteLine("Enter a phone number.");
telNo = Console.ReadLine();
if (telNo.Length > 8)
{
if (telNo.StartsWith("+") == true)
{
char[] arr = telNo.ToCharArray();
for (int a = 1; a < telNo.Length; a++)
{
int temp;
try
{
temp = arr[a];
}
catch
{
break;
}
if (a == telNo.Length - 1)
{
condition = true;
}
}
}
}
}
return true;
}
Don't try and do this yourself, use a library where someone has already done the hard work for you, such as libphonenumber.
Example:
public static bool validTelephoneNo(string telNo)
{
PhoneNumber number;
try
{
number = PhoneNumberUtil.Instance.Parse(telNo, "US"); // Change to your default language, international numbers will still be recognised.
}
catch (NumberParseException e)
{
return false;
}
return number.IsValidNumber;
}
This library will handle parsing and formatting phone numbers from different countries. Not only will this ensure that the number is valid in the relevant country, it will also allow you to filter out premium numbers and "fake" numbers (such as 555 in the US).
Your goal can be easily achieved using regular expressions:
public static bool validTelephoneNo(string telNo)
{
return Regex.Match(telNo, #"^\+\d{1,7}$").Success;
}
This pattern is exactly as stated: consists of integers, is less than 8 digits in length and has a plus at the start, and also this pattern can be modified if conditions somehow more complex.
try
Console.WriteLine("Enter a phone number.");
bool isValid = new System.Text.RegularExpressions.Regex(#"^[+]\d{1,7}$").IsMatch(Console.ReadLine());
Where the regex checks whether there is only a single number (1 to 7 digits) with + in front of them read. The drawback, this way you cannot further processed, you might need to read the line from console to a new variable.
I have a class that gathers 7-day forecast data from the Bureau or Meteorology and presents it on a web page. A script runs every 30 minutes to get updated data from the Bureau.
The bureau provides data in a tab delimited format with a header row. After extracting all the fields, I put the values into a Dictionary<string,string> for parsing. For obvious reasons, the important field for organising the data is the "forecast_date". So before I begin parsing, I make sure that my dictionary actually contains this key.
Here is a very simplified example of what I'm doing:
static object ForecastLockingObj= new object();
private void UpdateWeather()
{
if(isTimeForUpdate())
{
lock(ForecastLockingObj)
{
if(isTimeForUpdate())
{
Dictionary<string, string> ForecastData = Get7DayForecast();
int forecastDate = int.MinValue;
if (ForecastData.ContainsKey("forecast_date") && int.TryParse(ForecastData["forecast_date"], out forecastDate))
{
//Parse the data
SetNextUpdateTime();
}
}
}
}
}
This actually works for the most part. But very occasionally I'll get the following exception:
[KeyNotFoundException: The given key was not present in the dictionary.]
System.ThrowHelper.ThrowKeyNotFoundException() +28
System.Collections.Generic.Dictionary`2.get_Item(TKey key) +7457036
CoA.WebUI.Controls.WeatherWidget.UpdateWeather() in C:\dev\WeatherWidget.cs:231
Where line 231 is the if statement that checks the existence of "forecast_date" then attempts to parse it into an integer. Note; the service reliably renders dates as integers (e.g. 20130515) and so this is more of a sanity check.
ContainsKey should not be throwing this exception, so I feel it must be where I refer to ForecastData["forecast_date"] in my TryParse.
My question is this; surely if ContainsKey returns false, then TryParse should not run. So why would it report the existence of a key in one statement and then deny its existence in the very next statement... whilst we are inside a lock and the Dictionary we're working on is non-static and local?
As an aside; this typically happens in the afternoon, when the Bureau releases the next long range forecast. The exception happens for a few page-loads and then rights itself.
Here is the full Get7DayForecast method
private Dictionary<string, string> Get7DayForecast()
{
int linenumber = 0;
int locationNameKey = 0;
List<string> keys = new List<string>();
Dictionary<string, string> myLocationData = new Dictionary<string, string>();
FtpWebRequest ftp = (FtpWebRequest)WebRequest.Create(ForecastURL);
ftp.Method = WebRequestMethods.Ftp.DownloadFile;
ftp.Credentials = new NetworkCredential();
FtpWebResponse ftp_response = (FtpWebResponse)ftp.GetResponse();
if (ftp_response.WelcomeMessage.StartsWith("230") && ftp_response.StatusDescription.StartsWith("150"))
{
Stream ftp_responseStream = ftp_response.GetResponseStream();
StreamReader ftp_reader = new StreamReader(ftp_responseStream);
while (ftp_reader.Peek() >= 0)
{
linenumber++;
string line = ftp_reader.ReadLine();
List<string> temp = (List<string>)line.Split(ForecastDelimiter).ToList<string>();
if (linenumber == 1)
{
//Break if the header line does not contain the fields we require
if (!ForecastRequiredFields.All(line.Contains)) { break; }
keys = temp;
locationNameKey = keys.IndexOf(ForecastLocationFieldName);
}
else if (temp.Count == keys.Count && temp[locationNameKey] == ForecastLocationName)
{
for (int i = 0; i < keys.Count; i++)
{
myLocationData.Add(keys[i], temp[i]);
}
//Break if we've just parsed the data we were looking for
break;
}
}
ftp_reader.Close();
}
ftp_response.Close();
return myLocationData;
}
Honestly I cannot see why your code would fail but you should consider taking advantage of Trace to see what is up. Also it couldn't hurt to use TryGetValue instead.
var map = Get7DayForecast();
string forecastDateString;
if (!map.TryGetValue("forecast_date", out forecastDateString))
{
Trace.WriteLine("forecast_date entry was not found.");
return;
}
int foreCastDate;
if (!int.TryParse(forecastDateString, out foreCastDate)
{
Trace.WriteLine("Value was not a valid integer: " + forecastDateString);
return;
}
SetNextUpdateTime();