Rotate a number 180 degrees and get the same number - c#

I thought the problem of rotating a number 180 degrees clockwise ( or ccw) and getting the same number. For all digits, except 3, 4 and 7, the rotated one is a valid digit. (rotate 3 and you get ε). I'm new in C# but I managed to solve it.
public static bool MyMethod(int originalInt)
{
bool is180 = false;
if (Array.IndexOf(originalInt.ToString().ToArray(), '3') > -1 || Array.IndexOf(originalInt.ToString().ToArray(), '4') > -1 || Array.IndexOf(originalInt.ToString().ToArray(), '7') > -1)
{
return false;
}
else
{
List<int> tempList = new List<int>();
int tempInt = originalInt;
do
{
int lastDigit = tempInt % 10;
if (lastDigit == 9)
{
lastDigit = 6;
}
else if (lastDigit == 6)
{
lastDigit = 9;
}
tempInt = tempInt / 10;
tempList.Add(lastDigit);
}
while (tempInt > 0);
tempList.Reverse();
int tempInt2 = originalInt;
int lastDigit2 = 0;
foreach (int item in tempList)
{
lastDigit2 = tempInt2 % 10;
if (item == lastDigit2)
{
is180 = true;
tempInt2 = tempInt2 / 10;
}
else
{
return false;
}
}
}
return is180;
}
Can you find a way of solving this simpler? Thank you.

Pseudocode:
map['0'] = '0';
map['1'] = '1';
map['2'] = '2';
map['5'] = '5';
map['6'] = '9';
map['8'] = '8';
map['9'] = '6';
for each position i in input_string :
if map index exists for input_string[i] :
rotated_string[i] = map[input_string[i]]
else
exit for
rotated_string = reverse(rotated_string)
if input_string = rotated_string :
has_rotational_symmetry = true
else
has_rotational_symmetry = false

I'm not 100% sure what you are asking.. but the following returns true and false properly for your method...
Edit: Now with Lippertization!
public static bool MyMethod(int originalInt)
{
var s = originalInt.ToString();
return !(s.Contains('3') || s.Contains('4') || s.Contains('7'));
}

Couldn't resist an F# version:
let is180 s =
let rd = function|'0'->'0'|'1'->'1'|'2'->'2'|'5'->'5'|'6'->'9'|'8'->'8'|'9'->'6'|_->'X'
let flip x = new string(x |> Seq.map rd |> Seq.toArray |> Array.rev)
s.Equals(flip s)

Related

Check patterns of 5 in password "12345", "abcde"

I'm trying to validate a password string in a .NET for sequential patterns (forward or reverse) with numbers or letters of 5 or more.
Examples of patterns that will not be accepted:
"ABCDE",
"12345",
"54321",
"edcba"
I cannot find a decent regex pattern that handles finding the characters in order, currently just returning any sequence of 5 letters or numbers:
public bool CheckForSequence(string input)
{
return Regex.IsMatch(input.ToUpper(), #"([A-Z])(?!\1)([A-Z])(?!\1|\2)([A-Z])(?!\1|\2|\3)([A-Z])(?!\1|\2|\3|\4)([A-Z])") ||
Regex.IsMatch(input, #"([1-9])(?!\1)([1-9])(?!\1|\2)([1-9])(?!\1|\2|\3)([1-9])(?!\1|\2|\3|\4)([1-9])");
}
There are probably way better ways to do this, but, just for fun, I've made a simple brute-force algorithm:
bool CheckForSequence(string inp) {
bool InRange(int c) {
const int minLower = (int)'a';
const int maxLower = (int)'z';
const int minUpper = (int)'A';
const int maxUpper = (int)'Z';
const int minNumber = (int)'0';
const int maxNumber = (int)'9';
return (c >= minLower && c <= maxLower) || (c >= minUpper && c <= maxUpper) || (c >= minNumber && c <= maxNumber);
}
if(inp.Length < 5) return false;
for(var i = 0; i < inp.Length - 4; i++)
{
var c = (int)inp[i];
if(InRange(c))
{
var vM = c;
int x;
for(x = i+1; x < i + 5; x++)
{
if(inp[x] != vM+1 || !InRange(inp[x])) break;
vM++;
}
if(x == i+5) return true;
for(x = i+1; x < i + 5; x++)
{
if(inp[x] != vM-1 || !InRange(inp[x])) break;
vM--;
}
if(x == i+5) return true;
}
}
return false;
}
You can see it in action in this fiddle
Wiktor is correct - regex is the wrong tool for this.
Here's one possible implementation:
public static class SequenceChecker
{
private static char MapChar(char c) => c switch
{
>= '0' and <= '9' => c,
>= 'A' and <= 'Z' => c,
>= 'a' and <= 'z' => (char)(c - 'a' + 'A'),
_ => default,
};
private static bool IsSequence(ReadOnlySpan<char> input)
{
char x = MapChar(input[0]);
if (x == default) return false;
char y = MapChar(input[1]);
if (y == default) return false;
int direction = y - x;
if (Math.Abs(direction) != 1) return false;
for (int index = 2; index < input.Length; index++)
{
x = y;
y = MapChar(input[index]);
if (y == default) return false;
int nextDirection = y - x;
if (nextDirection != direction) return false;
}
return true;
}
public static bool ContainsSequence(string input, int sequenceLength = 5)
{
if (sequenceLength < 2) throw new ArgumentOutOfRangeException(nameof(sequenceLength));
if (input is null) return false;
if (input.Length < sequenceLength) return false;
for (int startIndex = 0; startIndex < 1 + input.Length - sequenceLength; startIndex++)
{
if (IsSequence(input.AsSpan(startIndex, sequenceLength)))
{
return true;
}
}
return false;
}
}
Just to add to the plethora of solutions posted so far:
public static int LongestAscendingOrDescendingRun(string s)
{
if (s.Length <= 1)
return 0;
int longest = 0;
int current = 0;
bool ascending = false;
for (int i = 1; i < s.Length; i++)
{
bool isAscending () => s[i]-s[i-1] == +1;
bool isDescending() => s[i]-s[i-1] == -1;
if (current > 0)
{
if (ascending)
{
if (isAscending())
{
longest = Math.Max(longest, ++current);
}
else // No longer ascending.
{
current = 0;
}
}
else // Descending.
{
if (isDescending())
{
longest = Math.Max(longest, ++current);
}
else // No longer descending.
{
current = 0;
}
}
}
else // No current.
{
if (isAscending())
{
ascending = true;
current = 2;
longest = Math.Max(longest, current);
}
else if (isDescending())
{
ascending = false;
current = 2;
longest = Math.Max(longest, current);
}
}
}
return longest;
}
Like Wiktor has already said, regex isn't a good way to do this. You could find the difference between consecutive characters of the string, and complain if you find a sequence of four or more ones (or -1s).
public bool CheckForSequence(string pass)
{
int curr_diff = 0; // The difference between the i-1th and i-2th character
int consec_diff = 0; // The number of consecutive pairs having the same difference
for (int i = 1; i < pass.Length; i++)
{
int diff = pass[i] - pass[i - 1]; // The difference between the ith and i-1th character
if (Math.Abs(diff) == 1 && curr_diff == diff)
{
// If the difference is the same, increment consec_diff
// And check if the password is invalid
consec_diff++;
if (consec_diff >= 4)
return false;
}
else
{
// New diff. reset curr_diff and consec_diff
curr_diff = diff;
consec_diff = Math.Abs(diff)==1 ? 1 : 0;
// If the difference is 1, set consec_diff to 1 else 0
}
}
return consec_diff < 4;
}

Checking for consecutive numbers

I'm trying to implement a method for checking consecutive numbers in C#.
Given an integer list of n elements, it should return true/false if the numbers are consecutive.
So for example, 12345, 45678, 54321 would all be true.
And 435276, 243516, 974264 would be false.
My code seems to be performing as expected. But it's missing the end element.
for (int i = 0; i < inputList.Count - 1; i++)
{
if (inputList[i] < inputList[i + 1])
{
Console.WriteLine($"{inputList[i]} is consecutive when compared to {inputList[i + 1]}");
consecutiveCheck = true;
}
else
{
Console.WriteLine($"{inputList[i]} is not consecutive when compared to {inputList[i + 1]}");
consecutiveCheck = false;
break;
}
}
Here's a simple way to do it:
int[] inputList = new [] { 12345, 45678, 54321 };
bool all_increasing = inputList.Zip(inputList.Skip(1), (x0, x1) => x1 > x0).All(x => x);
What are Consecutive numbers
It is series of number which have equal distance.
Example of Consecutive numbers
1,2,3,4,5
1,3,5,7,9
Example of NO Consecutive numbers
1,2,4,8,11
1,3,6,10,11
int diff = 0;
for (var i = 0; i < numbersInput.Length-1; i++)
{
if(i==0)
{
diff = numbersInput[i + 1] - numbersInput[i];
}
else if(numbersInput[i] + diff != numbersInput[i+1])
{
return false;
}
}
return true;
You mean you are checking if they are increasing:
bool inc = true;
for (int i = 1; i < inputList.Count; i++)
{
if (inputList[i] < inputList[i - 1])
{
inc=false;
break;
}
}
Console.WriteLine($"List has consecutive numbers: {(inc?"yes":"no")}");
This code will work :
private static bool isConsecutive(int[] list)
{
switch (list.Length)
{
case 0:
throw new ArgumentException("Value cannot be an empty collection.", nameof(list));
case 1:
throw new ArgumentException("This collection contains only one element.", nameof(list));
}
int direction = list[1]-list[0];
for (var index = 0; index < list.Length; index++)
{
int nextIndex = index + 1;
if (nextIndex >= list.Length)
{
continue;
}
int diff = list[nextIndex] - list[index];
if (diff != direction)
{
return false;
}
}
return true;
}

C# Tic-Tac-Toe Minimax

I am currently trying my hand at making a minimax AI for tictactoe. My goal was that it should suffice for larger boards as well. However, I am having quite a hard time wrapping my head around how to implement the algorithm. I have read countless different descriptions of the algorithm but I still don't seem to be able to make it work. My result as of yet is an incredibly stupid AI. Here is my code for it.
Edit: The main point I am wondering about is how I make the AI value me not winning over forwarding itself towards the win. As of now it doesn't really care that I will win the next turn.
namespace TicTacToe_AI
{
public class Move //A class for moves
{
public int x, y, value, MoveNumber;
void SetMove(int a, int b)
{
x = a;
y = b;
}
public Move(int a, int b)
{
SetMove(a, b);
}
public Move()
{ }
}
class AI //AIClass
{
//The minimax algorithm
public Move CalculateMoves(int[,] Board, int BoardSize, int Depth, Move BestMoveAI, Move BestMovePlayer, int OriginalDepth, int CurrentTurn)
{
Depth--; //Decrease the depth for each iteration
bool Alpha = false; //Alpha-beta pruning - needs improvement
bool Beta = false;
bool WinningMove = false;
if (CurrentTurn == 1) CurrentTurn = 2;
if (CurrentTurn == 2) CurrentTurn = 1;
List<Move> DifferentMoves = new List<Move>();
List<Move> PossibleMoves = new List<Move>();
for (int i = 0; i < BoardSize; i++) //Add all possible moves to a list
{
for (int j = 0; j < BoardSize; j++)
{
if (Board[i, j] == 0)
{
Move Possible = new Move(i, j);
PossibleMoves.Add(Possible);
}
}
}
if (CurrentTurn == 2 && Depth >= 0 && Depth < BestMoveAI.MoveNumber) Alpha = true; //Alpha-beta pruning
if (CurrentTurn == 1 && Depth >= 0 && Depth < BestMovePlayer.MoveNumber) Beta = true;
if(Alpha || Beta)
{
foreach (Move TryMove in PossibleMoves) //Try every possible move to see if they are a winning move
{
int[,] Trying = new int[BoardSize, BoardSize];
Trying = (int[,])Board.Clone();
Trying[TryMove.x, TryMove.y] = CurrentTurn;
TryMove.MoveNumber = OriginalDepth - Depth;
if (Form1.Win(Trying) == 2)
{
TryMove.value = -1;
DifferentMoves.Add(TryMove);
if (Depth + 1 == OriginalDepth)
{
if (TryMove.MoveNumber < BestMoveAI.MoveNumber) BestMoveAI = TryMove;
WinningMove = true;
break;
}
else
{
WinningMove = true;
if (TryMove.MoveNumber < BestMoveAI.MoveNumber) BestMoveAI = TryMove;
return TryMove;
}
}
else if (Form1.Win(Trying) == 1)
{
WinningMove = true;
TryMove.value = 1;
BestMovePlayer = TryMove;
DifferentMoves.Add(TryMove);
return TryMove;
}
}
if (!WinningMove) // If no winning move was found, try recursively searching for a winning move
{
if (Alpha || Beta)
{
foreach (Move TryMove2 in PossibleMoves)
{
int[,] TestMove = new int[BoardSize, BoardSize];
TestMove = (int[,])Board.Clone();
TestMove[TryMove2.x, TryMove2.y] = CurrentTurn;
TryMove2.value = CalculateMoves(TestMove, BoardSize, Depth, BestMoveAI, BestMovePlayer, OriginalDepth, CurrentTurn).value;
DifferentMoves.Add(TryMove2);
}
}
}
}
//Find the best possible move and return it
BestMoveAI.value = 0;
BestMoveAI.MoveNumber = OriginalDepth;
BestMovePlayer.value = 0;
BestMovePlayer.MoveNumber = OriginalDepth;
if (CurrentTurn == 2)
{
foreach (Move AllMoves in DifferentMoves)
{
if (AllMoves.value <= BestMoveAI.value && AllMoves.MoveNumber <= BestMoveAI.MoveNumber)
{
BestMoveAI = AllMoves;
}
}
return BestMoveAI;
}
else if(CurrentTurn == 1)
{
foreach (Move AllMoves in DifferentMoves)
{
if (AllMoves.value >= BestMovePlayer.value && AllMoves.MoveNumber <= BestMovePlayer.MoveNumber)
{
BestMovePlayer = AllMoves;
}
}
return BestMovePlayer;
}
Move BadMove = new Move();
BadMove.value = 0;
BadMove.MoveNumber = Depth;
return BadMove;
}
}
}

How can I get the binary search method to return false?

I am working on the binary search method in C# as an exercise, and it returns true if the number is in the list, but I cannot get it to return false if the number is not in the list. I had thought about doing else if at the end with conditions that the UB = LB, but the SearchKey does not equal the MP. Any suggestions?
static bool search(List<int> numbers, int searchKey)
{
int UB = numbers.Count - 1;
int LB = 0;
int MP = (UB + LB) / 2;
bool done = false;
do
{
if (numbers[MP] > searchKey)
{
UB = MP - 1;
MP = (UB + LB) / 2;
}
else if (numbers[MP] < searchKey)
{
LB = MP + 1;
MP = (UB + LB) / 2;
}
else if (numbers[MP] == searchKey)
{
done = true;
return true;
}
else
{
done = true;
return false;
}
} while (!done);
return false;
}
add this condition in your while loop while (!done && LB < UB);
It runs Infinite time when no item is search

Ray/AABB Intersection Incorrect

I've tried to reimplement the Fast Graphics Gems Ray/AABB Intersection Method in C#:
// Based on "Fast Ray-Box Intersection" algorithm by Andrew Woo, "Graphics Gems", Academic Press, 1990
public unsafe Vector? IntersectionWith(Cuboid other) {
const int NUM_DIMENSIONS = 3;
Assure.Equal(NUM_DIMENSIONS, 3); // If that value is ever changed, this algorithm will need some maintenance
const byte QUADRANT_MIN = 0;
const byte QUADRANT_MAX = 1;
const byte QUADRANT_BETWEEN = 2;
// Step 1: Work out which direction from the start point to test for intersection for all 3 dimensions, and the distance
byte* quadrants = stackalloc byte[NUM_DIMENSIONS];
float* candidatePlanes = stackalloc float[NUM_DIMENSIONS];
float* cuboidMinPoints = stackalloc float[NUM_DIMENSIONS];
float* cuboidMaxPoints = stackalloc float[NUM_DIMENSIONS];
float maxDistance = Single.NegativeInfinity;
byte maxDistanceDimension = 0;
bool startPointIsInsideCuboid = true;
cuboidMinPoints[0] = other.X;
cuboidMinPoints[1] = other.Y;
cuboidMinPoints[2] = other.Z;
cuboidMaxPoints[0] = other.X + other.Width;
cuboidMaxPoints[1] = other.Y + other.Height;
cuboidMaxPoints[2] = other.Z + other.Depth;
for (byte i = 0; i < NUM_DIMENSIONS; ++i) {
if (StartPoint[i] < cuboidMinPoints[i]) {
quadrants[i] = QUADRANT_MIN;
candidatePlanes[i] = cuboidMinPoints[i];
startPointIsInsideCuboid = false;
}
else if (StartPoint[i] > cuboidMaxPoints[i]) {
quadrants[i] = QUADRANT_MAX;
candidatePlanes[i] = cuboidMaxPoints[i];
startPointIsInsideCuboid = false;
}
else {
quadrants[i] = QUADRANT_BETWEEN;
}
}
if (startPointIsInsideCuboid) return StartPoint;
// Step 2: Find farthest dimension from cuboid
for (byte i = 0; i < NUM_DIMENSIONS; ++i) {
// ReSharper disable once CompareOfFloatsByEqualityOperator Exact check is desired here: Anything other than 0f is usable
if (quadrants[i] != QUADRANT_BETWEEN && Orientation[i] != 0f) {
float thisDimensionDist = (candidatePlanes[i] - StartPoint[i]) / Orientation[i];
if (thisDimensionDist > maxDistance) {
maxDistance = thisDimensionDist;
maxDistanceDimension = i;
}
}
}
if (maxDistance < 0f) return null;
if (maxDistance - Length > MathUtils.FlopsErrorMargin) return null;
float* intersectionPoint = stackalloc float[NUM_DIMENSIONS];
for (byte i = 0; i < NUM_DIMENSIONS; ++i) {
if (maxDistanceDimension == i) {
intersectionPoint[i] = StartPoint[i] + maxDistance * Orientation[i];
if (cuboidMinPoints[i] - intersectionPoint[i] > MathUtils.FlopsErrorMargin || intersectionPoint[i] - cuboidMaxPoints[i] > MathUtils.FlopsErrorMargin) return null;
}
else intersectionPoint[i] = candidatePlanes[i];
}
Vector result = new Vector(intersectionPoint[0], intersectionPoint[1], intersectionPoint[2]);
if (!IsInfiniteLength && Vector.DistanceSquared(StartPoint, result) > Length * Length) return null;
else return result;
}
However, although it sort of works, I'm getting incorrect results on the following part of a unit test:
Cuboid cuboid = new Cuboid(frontBottomLeft: new Vector(0f, 7.1f, 0f), width: 0f, height: 5f, depth: 0f);
Ray testRayC = new Ray(startPoint: new Vector(30f, 30f, 30f), orientation: new Vector(-1f, -1f, -1f));
Assert.AreEqual(
null,
testRayC.IntersectionWith(cuboid)
);
I am expecting null from the call to testRayC.IntersectionWith(cuboid), but instead it returns a Vector(0, 12.1, 0), which is not a point on the ray at all.
So is it just a case of adding a final check that the calculated point is on the ray? Or (and this is what I suspect), have I made an error in transcribing the code? I have double and triple checked but didn't see anything obvious...
The problem in your code is when you do if (maxDistanceDimension == i) {. The original code checks if (whichPlane != i) {. I don't have your data structures, but a fix should look like:
for (byte i = 0; i < NUM_DIMENSIONS; ++i)
{
if (maxDistanceDimension != i)
{
intersectionPoint[i] = StartPoint[i] + maxDistance * Orientation[i];
if (intersectionPoint[i] < cuboidMinPoints[i] - MathUtils.FlopsErrorMargin || intersectionPoint[i] > cuboidMaxPoints[i] + MathUtils.FlopsErrorMargin)
return null;
}
else
{
intersectionPoint[i] = candidatePlanes[i];
}
}
Next, the following isn't in the original code. What is this for?
if (maxDistance - Length > MathUtils.FlopsErrorMargin)
return null;
If you are trying to check if the hit is within the extent of the ray, this may be a bug. Given that your Orientation does not appear to be normalized, maxDistance is not necessarily in units of length. This may not matter in the original algorithm, but if you are going to check maxDistance against some other length you need to normalize Orientation (make it dimensionless) so that
thisDimensionDist = (candidatePlanes[i] - StartPoint[i]) / Orientation[i];
will have units of length.
Incidentally, in the original I think the following is wrong:
if(inside) {
coord = origin;
return (TRUE);
}
Assuming this code is c and not c++, this simply sets the the coord pointer to have the same reference as the origin pointer, which will have no effect on the caller. This issue doesn't apply to your version, however.
Also, in the course of looking at this, I made a more literal c# transcription of the algorithm here:
public static class RayXCuboid
{
enum HitQuadrant
{
Right = 0,
Left = 1,
Middle = 2,
}
const int Dimension = 3;
[Conditional("DEBUG")]
static void AssertValidArguments<TDoubleList>(params TDoubleList[] args) where TDoubleList : IList<double>
{
Debug.Assert(Dimension == 3);
foreach (var list in args)
Debug.Assert(list != null && list.Count == Dimension);
}
public static bool HitBoundingBox<TDoubleList>(TDoubleList minB, TDoubleList maxB, TDoubleList origin, TDoubleList dir, TDoubleList coord) where TDoubleList : IList<double>
{
AssertValidArguments(minB, maxB, origin, dir, coord);
HitQuadrant[] quadrant = new HitQuadrant[Dimension];
double[] maxT = new double[Dimension];
double[] candidatePlane = new double[Dimension];
/* Find candidate planes; this loop can be avoided if
rays cast all from the eye(assume perpsective view) */
bool inside = true;
for (int i = 0; i < Dimension; i++)
if (origin[i] < minB[i])
{
quadrant[i] = HitQuadrant.Left;
candidatePlane[i] = minB[i];
inside = false;
}
else if (origin[i] > maxB[i])
{
quadrant[i] = HitQuadrant.Right;
candidatePlane[i] = maxB[i];
inside = false;
}
else
{
quadrant[i] = HitQuadrant.Middle;
}
/* Ray origin inside bounding box */
if (inside)
{
CopyTo(origin, coord);
return true;
}
/* Calculate T distances to candidate planes */
for (int i = 0; i < Dimension; i++)
if (quadrant[i] != HitQuadrant.Middle && dir[i] != 0.0)
maxT[i] = (candidatePlane[i] - origin[i]) / dir[i];
else
maxT[i] = -1.0;
/* Get largest of the maxT's for final choice of intersection */
int whichPlane = 0;
for (int i = 1; i < Dimension; i++)
if (maxT[whichPlane] < maxT[i])
whichPlane = i;
/* Check final candidate actually inside box */
if (maxT[whichPlane] < 0.0)
{
FillWithDefault(coord);
return false;
}
for (int i = 0; i < Dimension; i++)
if (whichPlane != i)
{
coord[i] = origin[i] + maxT[whichPlane] * dir[i];
if (coord[i] < minB[i] || coord[i] > maxB[i])
{
FillWithDefault(coord);
return false;
}
}
else
{
coord[i] = candidatePlane[i];
}
return true; /* ray hits box */
}
static void FillWithDefault<T>(IList<T> list)
{
for (int i = 0; i < list.Count; i++)
list[i] = default(T);
}
static void CopyTo<T>(IList<T> from, IList<T> to)
{
int arrayIndex = 0;
foreach (var item in from)
to[arrayIndex++] = item;
}
}

Categories