How to validate a Singaporean FIN? - algorithm

Can anyone provide an algorithm to validate a Singaporean FIN?
I know with a Singaporean NRIC I can validate it via modulo 11 and then compare the result to a lookup table but cannot find a similar lookup table for the FIN.
I also do not know for sure if the modulo 11 is the correct method to validate.
I am aware the government sells a algorithm for $400 but maybe someone knows a cheaper way.
Bonus points for c# implementation.

And again in PHP
function isNricValid ($theNric) {
$multiples = array( 2, 7, 6, 5, 4, 3, 2 );
if (!$theNric || $theNric == '')
{
return false;
}
if (strlen($theNric) != 9)
{
return false;
}
$total = 0;
$count = 0;
$numericNric = 0;
$first = $theNric[0];
$last = $theNric[strlen($theNric) - 1];
if ($first != 'S' && $first != 'T')
{
return false;
}
$numericNric = substr($theNric, 1, strlen($theNric) - 2);
if (!is_numeric ($numericNric)) {
return false;
}
while ($numericNric != 0)
{
$total += ($numericNric % 10) * $multiples[sizeof($multiples) - (1 + $count++)];
$numericNric /= 10;
$numericNric = floor($numericNric);
}
$outputs = '';
if (strcmp($first, "S") == 0)
{
$outputs = array( 'J', 'Z', 'I', 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A' );
}
else
{
$outputs = array( 'G', 'F', 'E', 'D', 'C', 'B', 'A', 'J', 'Z', 'I', 'H' );
}
return $last == $outputs[$total % 11];
}
function isFinValid ($fin)
{
$multiples = array( 2, 7, 6, 5, 4, 3, 2 );
if (!$fin || $fin == '')
{
return false;
}
if (strlen($fin) != 9)
{
return false;
}
$total = 0;
$count = 0;
$numericNric = 0;
$first = $fin[0];
$last = $fin[strlen($fin) - 1];
if ($first != 'F' && $first != 'G')
{
return false;
}
$numericNric = substr($fin, 1, strlen($fin) - 2);
if (!is_numeric ($numericNric)) {
return false;
}
while ($numericNric != 0)
{
$total += ($numericNric % 10) * $multiples[sizeof($multiples) - (1 + $count++)];
$numericNric /= 10;
$numericNric = floor($numericNric);
}
$outputs = array();
if (strcmp($first, 'F') == 0)
{
$outputs = array( 'X', 'W', 'U', 'T', 'R', 'Q', 'P', 'N', 'M', 'L', 'K' );
}
else
{
$outputs = array( 'R', 'Q', 'P', 'N', 'M', 'L', 'K', 'X', 'W', 'U', 'T' );
}
return $last == $outputs[$total % 11];
}

Here's similar code written in JavaScript
var nric = [];
nric.multiples = [ 2, 7, 6, 5, 4, 3, 2 ];
nric.isNricValid = function (theNric) {
if (!theNric || theNric == '')
{
return false;
}
if (theNric.length != 9)
{
return false;
}
var total = 0
, count = 0
, numericNric;
var first = theNric[0]
, last = theNric[theNric.length - 1];
if (first != 'S' && first != 'T')
{
return false;
}
numericNric = theNric.substr(1, theNric.length - 2);
if (isNaN(numericNric)) {
return false
}
while (numericNric != 0)
{
total += (numericNric % 10) * nric.multiples[nric.multiples.length - (1 + count++)];
numericNric /= 10;
numericNric = Math.floor(numericNric);
}
var outputs;
if (first == 'S')
{
outputs = [ 'J', 'Z', 'I', 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A' ];
}
else
{
outputs = [ 'G', 'F', 'E', 'D', 'C', 'B', 'A', 'J', 'Z', 'I', 'H' ];
}
return last == outputs[total % 11];
}
nric.isFinValid = function(fin)
{
if (!fin || fin == '')
{
return false;
}
if (fin.length != 9)
{
return false;
}
var total = 0
, count = 0
, numericNric;
var first = fin[0]
, last = fin[fin.length - 1];
if (first != 'F' && first != 'G')
{
return false;
}
numericNric = fin.substr(1, fin.length - 2);
if (isNaN(numericNric)) {
return false;
}
while (numericNric != 0)
{
total += (numericNric % 10) * nric.multiples[nric.multiples.length - (1 + count++)];
numericNric /= 10;
numericNric = Math.floor(numericNric);
}
var outputs;
if (first == 'F')
{
outputs = [ 'X', 'W', 'U', 'T', 'R', 'Q', 'P', 'N', 'M', 'L', 'K' ];
}
else
{
outputs = [ 'R', 'Q', 'P', 'N', 'M', 'L', 'K', 'X', 'W', 'U', 'T' ];
}
return last == outputs[total % 11];
}

After a little searching around I found a way to validate them. This doesn't neccersarily mean the FIN is valid, just that it falls within a valid range.
I based it on algorithms from http://www.ngiam.net/NRIC/ppframe.htm
I've also included a similar method for checking NRIC because I figure anyone who comes across this and is interested in one is interested in the other as well.
Hope this helps someone!
private static readonly int[] Multiples = { 2, 7, 6, 5, 4, 3, 2 };
public static bool IsNricValid(string nric)
{
if (string.IsNullOrEmpty(nric))
{
return false;
}
// check length
if (nric.Length != 9)
{
return false;
}
int total = 0
, count = 0
, numericNric;
char first = nric[0]
, last = nric[nric.Length - 1];
if (first != 'S' && first != 'T')
{
return false;
}
if (!int.TryParse(nric.Substring(1, nric.Length - 2), out numericNric))
{
return false;
}
while (numericNric != 0)
{
total += numericNric % 10 * Multiples[Multiples.Length - (1 + count++)];
numericNric /= 10;
}
char[] outputs;
if (first == 'S')
{
outputs = new char[] { 'J', 'Z', 'I', 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A' };
}
else
{
outputs = new char[] { 'G', 'F', 'E', 'D', 'C', 'B', 'A', 'J', 'Z', 'I', 'H' };
}
return last == outputs[total % 11];
}
public static bool IsFinValid(string fin)
{
if (string.IsNullOrEmpty(fin))
{
return false;
}
// check length
if (fin.Length != 9)
{
return false;
}
int total = 0
, count = 0
, numericNric;
char first = fin[0]
, last = fin[fin.Length - 1];
if (first != 'F' && first != 'G')
{
return false;
}
if (!int.TryParse(fin.Substring(1, fin.Length - 2), out numericNric))
{
return false;
}
while (numericNric != 0)
{
total += numericNric % 10 * Multiples[Multiples.Length - (1 + count++)];
numericNric /= 10;
}
char[] outputs;
if (first == 'F')
{
outputs = new char[] { 'X', 'W', 'U', 'T', 'R', 'Q', 'P', 'N', 'M', 'L', 'K' };
}
else
{
outputs = new char[] { 'R', 'Q', 'P', 'N', 'M', 'L', 'K', 'X', 'W', 'U', 'T' };
}
return last == outputs[total % 11];
}

The below is the URL for NRIC & FIN algaritham.
http://www.arjun.com.np/blog/all-about-nric-number-in-singapore/
public class NRIC_FIN {
public static void main(String[] args) {
String idNumber = "T123d121J";
String NRIC = idNumber.toUpperCase();
String number;
int sum = 0;
if (NRIC.length() != 9) {
System.out.println("must be 9 digits..");
return;
}
number = NRIC.substring(1, 8);
if (!isNAN(at(number, 0)))
sum += valueOf(at(number, 0)) * 2;
if (!isNAN(at(number, 1)))
sum += valueOf(at(number, 1)) * 7;
if (!isNAN(at(number, 2)))
sum += valueOf(at(number, 2)) * 6;
if (!isNAN(at(number, 3)))
sum += valueOf(at(number, 3)) * 5;
if (!isNAN(at(number, 4)))
sum += valueOf(at(number, 4)) * 4;
if (!isNAN(at(number, 5)))
sum += valueOf(at(number, 5)) * 3;
if (!isNAN(at(number, 6)))
sum += valueOf(at(number, 6)) * 2;
if (NRIC.charAt(0) == 'T' || NRIC.charAt(0) == 'G') {
sum += 4;
}
char checkChar = NRIC.charAt(8);
double p = 11 - (sum % 11);
if (NRIC.charAt(0) == 'S' || NRIC.charAt(0) == 'T') {
if ((p == 1 && checkChar == 'A') || (p == 2 && checkChar == 'B')
|| (p == 3 && checkChar == 'C')
|| (p == 4 && checkChar == 'D')
|| (p == 5 && checkChar == 'E')
|| (p == 6 && checkChar == 'F')
|| (p == 7 && checkChar == 'G')
|| (p == 8 && checkChar == 'H')
|| (p == 9 && checkChar == 'I')
|| (p == 10 && checkChar == 'Z')
|| (p == 11 && checkChar == 'J')) {
System.out.println("true...NRIC");
}
}
if (NRIC.charAt(0) == 'F' || NRIC.charAt(0) == 'G') {
if ((p == 1 && checkChar == 'K') || (p == 2 && checkChar == 'M')
|| (p == 3 && checkChar == 'L')
|| (p == 4 && checkChar == 'N')
|| (p == 5 && checkChar == 'P')
|| (p == 6 && checkChar == 'Q')
|| (p == 7 && checkChar == 'R')
|| (p == 8 && checkChar == 'T')
|| (p == 9 && checkChar == 'U')
|| (p == 10 && checkChar == 'W')
|| (p == 11 && checkChar == 'X')) {
System.out.println("true ...FIN");
}
}
System.out.println("flase ...");
}
public static boolean isNAN(char c) {
return !Character.isDigit(c);
}
public static int valueOf(char c) {
return (((int) c) - 48);
}
public static char at(String from, int index) {
return from.charAt(index);
}
}

Related

Nesting depth and check of valid or invalid values

I have a script for counting the paranthese depth of a text. My function counts the depth and checks for open parantheses, and is supposed to return the following tupel: (depth, valid, balanced).
The depth is controlling how many valid parantheses the text contains.
Valid checks if there are to many or any closing paranthese missing their counterpart, of if its a negative value.
Balanced check controlls if the value is 0 or not.
s = '((This teXt)((is)(five deep((, valid))and))balanced)\t'
te = ''.join(s).lower()
par = ''
for ch in te:
if ch not in (' ', '\n', ',', '.', '-', '–', '—', '*',
'«', '»', ':', ';', '’', '?', "'", '"',
'/', '!', '…', '´', '`', '+', '[', ']',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9','a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', 'æ', 'ø', 'å', '\t'):
par += ch
def max_dep():
count = 0
max_num = 0
for i in par:
if i == '(':
count += 1
if max_num < count:
max_num = count
if i == ')':
count -= 1
val = 0
for t in par:
if t == '(':
val += 1
if t == ')':
val -= 1
if val == 0:
val = True
else:
val = False
bal = 0
for x in par:
if x == '(':
bal += 1
if x == ')':
bal -= 1
if bal == 0:
bal = True
else:
bal = False
return max_num, val, bal
print(max_dep())
Since 'val' = 0 and 'bal' = 0, I was hoping on the print (5, True, True), but as I hvae come to understand, 0 is never True. Is there any hope to get this function to print True for 0 or do I have to start over?
In short: The solution was to pull back the check/ statements from the for-loop.
'''s = '((This teXt)((is)(five deep((, valid))and))balanced)\t'
te = ''.join(s).lower()
par = ''
for ch in te:
if ch not in (' ', '\n', ',', '.', '-', '–', '—', '*',
'«', '»', ':', ';', '’', '?', "'", '"',
'/', '!', '…', '´', '`', '+', '[', ']',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9','a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', 'æ', 'ø', 'å', '\t'):
par += ch
def max_dep():
count = 0
max_num = 0
for i in par:
if i == '(':
count += 1
if max_num < count:
max_num = count
if i == ')':
count -= 1
val = 0
for t in par:
if t == '(':
val += 1
if t == ')':
val -= 1
if val < 0:
val = False
else:
val = True
bal = 0
for x in par:
if x == '(':
bal += 1
if x == ')':
bal -= 1
if bal == 0:
bal = True
else:
bal = False
return max_num, val, bal
print(max_dep())'''

Find a word (substring) in a string based on random character position

Let's say you have a string:
I like apples more than oranges.
And you get an Int as an input in the program, let's say 11.
Character no. 11 is the l in apples. Based on that number, what is the most efficient and elegant solution to get to apples?
As a reference, I am using Kotlin
Simply start at the given index and loop backwards until you reach the stop sequence (space, period or either end of string), and repeat the same thing moving forwards.
Here's an implementation of how it would work using Kotlin:
fun main() {
val str = "I like apples more than oranges."
println(findWord(str, 15))
}
fun findWord(str: String, index: Int):String {
var fi = 0
var li = str.length-1
var i = index-1
if(str[index] == ' ' || str[index] == '.')
return "Invalid Index"
while (i >= 0) {
if(str[i] == ' ' || str[i] == '.'){
fi = i
break
}
i--
}
i = index+1
while (i <= str.length-1) {
if(str[i] == ' ' || str[i] == '.'){
li = i
break
}
i++
}
fi = if(fi==0 && (str[fi] != ' ' && str[fi] != '.'))fi else fi+1
li = if(li==str.length-1 && (str[li] != ' ' && str[li] != '.'))li+1 else li
return str.substring(fi, li)
}

How can I structure nHibernate QueryOver where (X AND Y) OR (null AND null)

In SQL ease:
where (Id1 = #iX and Id2 = #iY) OR (id1 is null AND Id2 is null)
In (sudo/failed) nHibernate:
where (c => c.Id1 == iX AND c.Id2 == iY) OR (c => c.Id1 == null AND c.Id2 == null)
All helpful suggestions appreciated.
using criteria:
var r = ses.CreateCriteria<myT>()
.Add(Restrictions.Or(
Restrictions.And(Restrictions.Where<myT>((c) => c.Id1 == iX)
, Restrictions.Where<myT>((c) => c.Id2 == iY)
)
, Restrictions.And(Restrictions.Where<myT>((c) => c.Id1 == null)
, Restrictions.Where<myT>((c) => c.Id2 == null)
)
))
.List<myT>();
Nets a reasonable:
WHERE ((this_.Id1 = #p0 and this_.Id2 = #p1) or (this_.Id1 is null and this_.Id2 is null))
where #p0 = #iX and #p1 = #iY

All Possible Tic Tac Toe Winning Combinations

I had an interview were I was asked a seemingly simple algorithm question: "Write an algorithm to return me all possible winning combinations for tic tac toe." I still can't figure out an efficient way to handle this. Is there a standard algorithm or common that should be applied to similar questions like this that I'm not aware of?
This is one of those problems that's actually simple enough for brute force and, while you could use combinatorics, graph theory, or many other complex tools to solve it, I'd actually be impressed by applicants that recognise the fact there's an easier way (at least for this problem).
There are only 39, or 19,683 possible combinations of placing x, o or <blank> in the grid, and not all of those are valid.
First, a valid game position is one where the difference between x and o counts is no more than one, since they have to alternate moves.
In addition, it's impossible to have a state where both sides have three in a row, so they can be discounted as well. If both have three in a row, then one of them would have won in the previous move.
There's actually another limitation in that it's impossible for one side to have won in two different ways without a common cell (again, they would have won in a previous move), meaning that:
XXX
OOO
XXX
cannot be achieved, while:
XXX
OOX
OOX
can be. But we can actually ignore that since there's no way to win two ways without a common cell without having already violated the "maximum difference of one" rule, since you need six cells for that, with the opponent only having three.
So I would simply use brute force and, for each position where the difference is zero or one between the counts, check the eight winning possibilities for both sides. Assuming only one of them has a win, that's a legal, winning game.
Below is a proof of concept in Python, but first the output of time when run on the process sending output to /dev/null to show how fast it is:
real 0m0.169s
user 0m0.109s
sys 0m0.030s
The code:
def won(c, n):
if c[0] == n and c[1] == n and c[2] == n: return 1
if c[3] == n and c[4] == n and c[5] == n: return 1
if c[6] == n and c[7] == n and c[8] == n: return 1
if c[0] == n and c[3] == n and c[6] == n: return 1
if c[1] == n and c[4] == n and c[7] == n: return 1
if c[2] == n and c[5] == n and c[8] == n: return 1
if c[0] == n and c[4] == n and c[8] == n: return 1
if c[2] == n and c[4] == n and c[6] == n: return 1
return 0
pc = [' ', 'x', 'o']
c = [0] * 9
for c[0] in range (3):
for c[1] in range (3):
for c[2] in range (3):
for c[3] in range (3):
for c[4] in range (3):
for c[5] in range (3):
for c[6] in range (3):
for c[7] in range (3):
for c[8] in range (3):
countx = sum([1 for x in c if x == 1])
county = sum([1 for x in c if x == 2])
if abs(countx-county) < 2:
if won(c,1) + won(c,2) == 1:
print " %s | %s | %s" % (pc[c[0]],pc[c[1]],pc[c[2]])
print "---+---+---"
print " %s | %s | %s" % (pc[c[3]],pc[c[4]],pc[c[5]])
print "---+---+---"
print " %s | %s | %s" % (pc[c[6]],pc[c[7]],pc[c[8]])
print
As one commenter has pointed out, there is one more restriction. The winner for a given board cannot have less cells than the loser since that means the loser just moved, despite the fact the winner had already won on the last move.
I won't change the code to take that into account but it would be a simple matter of checking who has the most cells (the last person that moved) and ensuring the winning line belonged to them.
Another way could be to start with each of the eight winning positions,
xxx ---
--- xxx
--- --- ... etc.,
and recursively fill in all legal combinations (start with inserting 2 o's, then add an x for each o ; avoid o winning positions):
xxx xxx xxx
oo- oox oox
--- o-- oox ... etc.,
Today I had an interview with Apple and I had the same question. I couldn't think well at that moment. Later one on, before going to a meeting I wrote the function for the combinations in 15 minutes, and when I came back from the meeting I wrote the validation function again in 15 minutes. I get nervous at interviews, Apple not trusts my resume, they only trust what they see in the interview, I don't blame them, many companies are the same, I just say that something in this hiring process doesn't look quite smart.
Anyways, here is my solution in Swift 4, there are 8 lines of code for the combinations function and 17 lines of code to check a valid board.
Cheers!!!
// Not used yet: 0
// Used with x : 1
// Used with 0 : 2
// 8 lines code to get the next combination
func increment ( _ list: inout [Int], _ base: Int ) -> Bool {
for digit in 0..<list.count {
list[digit] += 1
if list[digit] < base { return true }
list[digit] = 0
}
return false
}
let incrementTicTacToe = { increment(&$0, 3) }
let win0_ = [0,1,2] // [1,1,1,0,0,0,0,0,0]
let win1_ = [3,4,5] // [0,0,0,1,1,1,0,0,0]
let win2_ = [6,7,8] // [0,0,0,0,0,0,1,1,1]
let win_0 = [0,3,6] // [1,0,0,1,0,0,1,0,0]
let win_1 = [1,4,7] // [0,1,0,0,1,0,0,1,0]
let win_2 = [2,5,8] // [0,0,1,0,0,1,0,0,1]
let win00 = [0,4,8] // [1,0,0,0,1,0,0,0,1]
let win11 = [2,4,6] // [0,0,1,0,1,0,1,0,0]
let winList = [ win0_, win1_, win2_, win_0, win_1, win_2, win00, win11]
// 16 lines to check a valid board, wihtout countin lines of comment.
func winCombination (_ tictactoe: [Int]) -> Bool {
var count = 0
for win in winList {
if tictactoe[win[0]] == tictactoe[win[1]],
tictactoe[win[1]] == tictactoe[win[2]],
tictactoe[win[2]] != 0 {
// If the combination exist increment count by 1.
count += 1
}
if count == 2 {
return false
}
}
var indexes = Array(repeating:0, count:3)
for num in tictactoe { indexes[num] += 1 }
// '0' and 'X' must be used the same times or with a diference of one.
// Must one and only one valid combination
return abs(indexes[1] - indexes[2]) <= 1 && count == 1
}
// Test
var listToIncrement = Array(repeating:0, count:9)
var combinationsCount = 1
var winCount = 0
while incrementTicTacToe(&listToIncrement) {
if winCombination(listToIncrement) == true {
winCount += 1
}
combinationsCount += 1
}
print("There is \(combinationsCount) combinations including possible and impossible ones.")
print("There is \(winCount) combinations for wining positions.")
/*
There are 19683 combinations including possible and impossible ones.
There are 2032 combinations for winning positions.
*/
listToIncrement = Array(repeating:0, count:9)
var listOfIncremented = ""
for _ in 0..<1000 { // Win combinations for the first 1000 combinations
_ = incrementTicTacToe(&listToIncrement)
if winCombination(listToIncrement) == true {
listOfIncremented += ", \(listToIncrement)"
}
}
print("List of combinations: \(listOfIncremented)")
/*
List of combinations: , [2, 2, 2, 1, 1, 0, 0, 0, 0], [1, 1, 1, 2, 2, 0, 0, 0, 0],
[2, 2, 2, 1, 0, 1, 0, 0, 0], [2, 2, 2, 0, 1, 1, 0, 0, 0], [2, 2, 0, 1, 1, 1, 0, 0, 0],
[2, 0, 2, 1, 1, 1, 0, 0, 0], [0, 2, 2, 1, 1, 1, 0, 0, 0], [1, 1, 1, 2, 0, 2, 0, 0, 0],
[1, 1, 1, 0, 2, 2, 0, 0, 0], [1, 1, 0, 2, 2, 2, 0, 0, 0], [1, 0, 1, 2, 2, 2, 0, 0, 0],
[0, 1, 1, 2, 2, 2, 0, 0, 0], [1, 2, 2, 1, 0, 0, 1, 0, 0], [2, 2, 2, 1, 0, 0, 1, 0, 0],
[2, 2, 1, 0, 1, 0, 1, 0, 0], [2, 2, 2, 0, 1, 0, 1, 0, 0], [2, 2, 2, 1, 1, 0, 1, 0, 0],
[2, 0, 1, 2, 1, 0, 1, 0, 0], [0, 2, 1, 2, 1, 0, 1, 0, 0], [2, 2, 1, 2, 1, 0, 1, 0, 0],
[1, 2, 0, 1, 2, 0, 1, 0, 0], [1, 0, 2, 1, 2, 0, 1, 0, 0], [1, 2, 2, 1, 2, 0, 1, 0, 0],
[2, 2, 2, 0, 0, 1, 1, 0, 0]
*/
This is a java equivalent code sample
package testit;
public class TicTacToe {
public static void main(String[] args) {
// TODO Auto-generated method stub
// 0 1 2
// 3 4 5
// 6 7 8
char[] pc = {' ' ,'o', 'x' };
char[] c = new char[9];
// initialize c
for (int i = 0; i < 9; i++)
c[i] = pc[0];
for (int i = 0; i < 3; i++) {
c[0] = pc[i];
for (int j = 0; j < 3; j++) {
c[1] = pc[j];
for (int k = 0; k < 3; k++) {
c[2] = pc[k];
for (int l = 0; l < 3; l++) {
c[3] = pc[l];
for (int m = 0; m < 3; m++) {
c[4] = pc[m];
for (int n = 0; n < 3; n++) {
c[5] = pc[n];
for (int o = 0; o < 3; o++) {
c[6] = pc[o];
for (int p = 0; p < 3; p++) {
c[7] = pc[p];
for (int q = 0; q < 3; q++) {
c[8] = pc[q];
int countx = 0;
int county = 0;
for(int r = 0 ; r<9 ; r++){
if(c[r] == 'x'){
countx = countx + 1;
}
else if(c[r] == 'o'){
county = county + 1;
}
}
if(Math.abs(countx - county) < 2){
if(won(c, pc[2])+won(c, pc[1]) == 1 ){
System.out.println(c[0] + " " + c[1] + " " + c[2]);
System.out.println(c[3] + " " + c[4] + " " + c[5]);
System.out.println(c[6] + " " + c[7] + " " + c[8]);
System.out.println("*******************************************");
}
}
}
}
}
}
}
}
}
}
}
}
public static int won(char[] c, char n) {
if ((c[0] == n) && (c[1] == n) && (c[2] == n))
return 1;
else if ((c[3] == n) && (c[4] == n) && (c[5] == n))
return 1;
else if ((c[6] == n) && (c[7] == n) && (c[8] == n))
return 1;
else if ((c[0] == n) && (c[3] == n) && (c[6] == n))
return 1;
else if ((c[1] == n) && (c[4] == n) && (c[7] == n))
return 1;
else if ((c[2] == n) && (c[5] == n) && (c[8] == n))
return 1;
else if ((c[0] == n) && (c[4] == n) && (c[8] == n))
return 1;
else if ((c[2] == n) && (c[4] == n) && (c[6] == n))
return 1;
else
return 0;
}
}
`
Below Solution generates all possible combinations using recursion
It has eliminated impossible combinations and returned 888 Combinations
Below is a working code Possible winning combinations of the TIC TAC TOE game
const players = ['X', 'O'];
let gameBoard = Array.from({ length: 9 });
const winningCombination = [
[ 0, 1, 2 ],
[ 3, 4, 5 ],
[ 6, 7, 8 ],
[ 0, 3, 6 ],
[ 1, 4, 7 ],
[ 2, 5, 8 ],
[ 0, 4, 8 ],
[ 2, 4, 6 ],
];
const isWinningCombination = (board)=> {
if((Math.abs(board.filter(a => a === players[0]).length -
board.filter(a => a === players[1]).length)) > 1) {
return false
}
let winningComb = 0;
players.forEach( player => {
winningCombination.forEach( combinations => {
if (combinations.every(combination => board[combination] === player )) {
winningComb++;
}
});
});
return winningComb === 1;
}
const getCombinations = (board) => {
let currentBoard = [...board];
const firstEmptySquare = board.indexOf(undefined)
if (firstEmptySquare === -1) {
return isWinningCombination(board) ? [board] : [];
} else {
return [...players, ''].reduce((prev, next) => {
currentBoard[firstEmptySquare] = next;
if(next !== '' && board.filter(a => a === next).length > (gameBoard.length / players.length)) {
return [...prev]
}
return [board, ...prev, ...getCombinations(currentBoard)]
}, [])
}
}
const startApp = () => {
let combination = getCombinations(gameBoard).filter(board =>
board.every(item => !(item === undefined)) && isWinningCombination(board)
)
printCombination(combination)
}
const printCombination = (combination)=> {
const ulElement = document.querySelector('.combinations');
combination.forEach(comb => {
let node = document.createElement("li");
let nodePre = document.createElement("pre");
let textnode = document.createTextNode(JSON.stringify(comb));
nodePre.appendChild(textnode);
node.appendChild(nodePre);
ulElement.appendChild(node);
})
}
startApp();
This discovers all possible combinations for tic tac toe (255,168) -- written in JavaScript using recursion. It is not optimized, but gets you what you need.
const [EMPTY, O, X] = [0, 4, 1]
let count = 0
let coordinate = [
EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY
]
function reducer(arr, sumOne, sumTwo = null) {
let func = arr.reduce((sum, a) => sum + a, 0)
if((func === sumOne) || (func === sumTwo)) return true
}
function checkResult() {
let [a1, a2, a3, b1, b2, b3, c1, c2, c3] = coordinate
if(reducer([a1,a2,a3], 3, 12)) return true
if(reducer([a1,b2,c3], 3, 12)) return true
if(reducer([b1,b2,b3], 3, 12)) return true
if(reducer([c1,c2,c3], 3, 12)) return true
if(reducer([a3,b2,c1], 3, 12)) return true
if(reducer([a1,b1,c1], 3, 12)) return true
if(reducer([a2,b2,c2], 3, 12)) return true
if(reducer([a3,b3,c3], 3, 12)) return true
if(reducer([a1,a2,a3,b1,b2,b3,c1,c2,c3], 21)) return true
return false
}
function nextPiece() {
let [countX, countO] = [0, 0]
for(let i = 0; i < coordinate.length; i++) {
if(coordinate[i] === X) countX++
if(coordinate[i] === O) countO++
}
return countX === countO ? X : O
}
function countGames() {
if (checkResult()) {
count++
}else {
for (let i = 0; i < 9; i++) {
if (coordinate[i] === EMPTY) {
coordinate[i] = nextPiece()
countGames()
coordinate[i] = EMPTY
}
}
}
}
countGames()
console.log(count)
I separated out the checkResult returns in case you want to output various win conditions.
Could be solved with brute force but keep in mind the corner cases like player2 can't move when player1 has won and vice versa. Also remember Difference between moves of player1 and player can't be greater than 1 and less than 0.
I have written code for validating whether provided combination is valid or not, might soon post on github.

Mix two lists in groovy according to a pattern in Groovy?

I have two lists lets say:
def list1 = [a,b,c,d,e...]
def list2 = [1,2,3,4,5... ]
I want them to mix in a certain pattern so that final list looks like:
[a,b,c,d,1,2,e,f,g,h,3,4,i,j,k,l,5,6...]
Basically after every n elements from list1, i get m elements from list2.
EDIT: If one list runs out of elements, the items in the remaining list should simply get added to the final list.
EDIT2: Both the lists can have objects as elements.
I want to find the most efficient way to solve this problem.
Here's one way of doing this in Groovy:
So I have a method mix which takes a map with Integer keys (the number of elements required), and Lists as values:
List mix( Map<Integer,List> amounts ) {
amounts.collect { k, v ->
v.collate( k )
}.transpose().flatten()
}
Then, given:
// The letters a to z
def list1 = 'a'..'z'
// The numbers 1 to 10
def list2 = 1..10
// Call, and ask for 4 of list1 followed by 2 of list2
mix( [ 4:list1, 2:list2 ] )
That returns:
[ 'a', 'b', 'c', 'd', 1, 2,
'e', 'f', 'g', 'h', 3, 4,
'i', 'j', 'k', 'l', 5, 6,
'm', 'n', 'o', 'p', 7, 8,
'q', 'r', 's', 't', 9, 10 ]
(formatted to look better here)
As you can see, it runs out of numbers first, and when it does, the list ends. This is because transpose stops when one list runs out of elements.
EDIT:
Worked out another way with Iterators (so it's lazy and won't use up more memory than is otherwise required):
class MixingIterator<T> implements Iterator<T> {
private int idx = 0
private List<Iterator> iter
private List<Integer> amts
MixingIterator( List<List> lists, List<Integer> amounts ) {
iter = lists*.iterator()
int i = 0
amts = amounts.collectMany { [ i++ ] * it }
// OR FOR GROOVY 1.7.8
// amts = amounts.collect { [ i++ ] * it }.flatten()
}
private void moveIdx() {
idx = ++idx % amts.size()
}
#Override boolean hasNext() {
iter*.hasNext().any()
}
#Override T next() {
if( !hasNext() ) { throw new NoSuchElementException() }
while( !iter[ amts[ idx ] ].hasNext() ) { moveIdx() }
T ret = iter[ amts[ idx ] ].next()
moveIdx()
ret
}
#Override void remove() {
throw new UnsupportedOperationException()
}
}
You call it by:
def list1 = 'a'..'z'
def list2 = 1..10
def ret = new MixingIterator( [ list1, list2 ], [ 4, 2 ] ).collect()
// OR FOR GROOVY 1.7.8
// def ret = new MixingIterator( [ list1, list2 ], [ 4, 2 ] ).collect { it }
And ret will then equal:
['a', 'b', 'c', 'd', 1, 2,
'e', 'f', 'g', 'h', 3, 4,
'i', 'j', 'k', 'l', 5, 6,
'm', 'n', 'o', 'p', 7, 8,
'q', 'r', 's', 't', 9, 10,
'u', 'v', 'w', 'x', 'y', 'z']
I have a functional solution preserving remaining elements based on the main answer.
List mix( Map<Integer,List> amounts ) {
def maxItems = amounts.collect { k, v -> v.size() }.max()
amounts.collect { k, v ->
def padding = maxItems - v.size()
it.addAll((1..padding).collect { null })
v.collate( k )
}.transpose().flatten().grep { it }
}
I tested it in a simplified version to mix three lists taking one item at time. The idea is just adding padding with null objects to make all of the same length.

Resources