Related
On a chessboard consisting of M rows and N columns (for example, 8x10), there are two knights, the user enters their coordinates himself (for example, (2, 4) is a white knight and (7, 9) is a black knight). Each knight is located in the it's cell, but it is possible that both knights are in the same cell.
The knights take turns making moves in accordance with the rules of the chess knight's movement (the white knight goes first). The goal of the game is to place both horses in the same cell as quickly as possible.
Input format
The first line of the file contains the values M and N (2≤M,N≤1000). The second and third lines contain the coordinates of the cells in which the white and black knight are located, respectively. The first coordinate is in the range from 1 to M, the second is in the range from 1 to N.
Output format
Print a single number — the number of moves required to complete the game. If the knights can never be placed in the same square, print -1.
Since I'm new to algorithms and data structures, I tried to solve this problem like this: run for loop on all 64 possible combinations of two moves of a white and black knight, make a move for each knight (checking if it goes beyond the scope), check if there is a match and, if there is, then output it. Then run the same cycle inside of the current. At the same time, the moves are counted and it is also output. However, I have encountered such a problem that I cannot automate the process of running this loop inside the loop, I cannot know the number of times that this loop needs to be run. I tried to create a function with recursion in which it was possible to call this loop if a match has not yet been found, but I failed.
I decided that it would not work that way to solve this problem, so I looked at the algorithms that are usually used in such tasks. I was thinking of somehow creating an adjacency list for two horses, where the vertices are all the calculated positions of the horse; use BFS, or the Dijkstra algorithm.
Solved.
Here is my swift code:
import Foundation
let mnstr = readLine()?.components(separatedBy: " ")
let m = Int(mnstr![0])!
let n = Int(mnstr![1])!
let wstr = readLine()?.components(separatedBy: " ")
let bstr = readLine()?.components(separatedBy: " ")
var w: [Int] = []
var b: [Int] = []
var count: Int = 0
let moves: [[Int]] = [[2, -1], [1, 2], [-2, -1], [1, -2], [2, 1], [-1, 2], [-2, 1], [-1, -2]]
w.append(Int(wstr![0])!)
w.append(Int(wstr![1])!)
b.append(Int(bstr![0])!)
b.append(Int(bstr![1])!)
var wp: Set = [w]
var bp: Set = [b]
func oneMove(lst: Set<[Int]>) -> Set<[Int]>{
let curr = lst
var out = lst
for i in curr {
for move in moves {
let item = [i[0] + move[0], i[1] + move[1]]
if item[0] < 1 || item[0] > m || item[1] < 1 || item[1] > n {
continue
}
out.insert(item)
}
}
return out
}
while bp.intersection(wp).isEmpty == true {
wp = oneMove(lst: wp)
count += 1
if wp.intersection(bp).isEmpty != true {
break
}
bp = oneMove(lst: bp)
count += 1
if wp.intersection(bp).isEmpty != true {
break
}
if wp.count == 1 || bp.count == 1 {
count = -1
break
}
}
print(count)
I know that an answer was already accepted, but for large distances between the pieces a BFS or Dijkstra's algorithm will use considerable time and resources.
There is however a pattern: when there is enough distance between the pieces (both in X and Y direction), an optimal path can be found within the bounding box of the two pieces and can be derived by a closed formula. And the more constrained or unsolvable situations can be identified also in constant time. The code for distinguishing the different patterns is quite "dull", but it will certainly run faster for when the paths are long: in constant time (if we assume arithmetic operations use constant time).
Here is some JavaScript code, which also includes the BFS algorithm so the outcome can be compared. It includes an interactive part, so that you can play with the board sizes and the positioning of the two pieces and check the results:
function knightDistance(rowCount, colCount, whiteX, whiteY, blackX, blackY) {
// Convert the state so to ensure that black is at the right & upper side of white, and below the diagonal
if (blackX < whiteX) return knightDistance(rowCount, colCount, blackX, blackY, whiteX, whiteY); // Swap pieces
if (blackY < whiteY) return knightDistance(rowCount, colCount, whiteX, rowCount - 1 - whiteY, blackX, rowCount - 1 - blackY); // Mirror against X axis
let diffX = blackX - whiteX;
let diffY = blackY - whiteY;
if (diffX < diffY) return knightDistance(colCount, rowCount, whiteY, whiteX, blackY, blackX); // mirror along diagonal
if (diffX == 2 && diffY == 2) return 4;
if (diffX <= 2 * diffY && diffX != 1) {
if ((diffX + diffY) % 2) return Math.floor((diffX + diffY + 1) / 6) * 2 + 1;
return Math.floor((diffX + diffY + 4) / 6) * 2;
}
if (rowCount == 1 || colCount == 2) return -1;
if (rowCount == 2 && diffX % 4 != 2 * diffY) return -1;
if (diffX + diffY > 3) {
if ((diffX + diffY) % 2) return Math.floor((diffX + 1) / 4) * 2 + 1;
return Math.floor((diffX + 3) / 4) * 2;
}
// Now rowCount > 2 and colCount > 2
// Other cases where lack of space plays a role
if (diffY == 1) {
// Now diffX == 1
if (rowCount == 3 && colCount == 3 && whiteX == whiteY) return -1;
if (whiteX == 0 && whiteY == 0 || blackX == colCount - 1 && blackY == rowCount - 1) return 4;
return 2;
}
// Now diffY == 0
if (diffX == 1) {
if (whiteY == 1 && rowCount == 3 && colCount == 3) return -1;
if (whiteY == 1 && rowCount == 3 && colCount == 4 && whiteX == 1) return 5;
return 3;
}
if (diffX == 2) {
if (whiteY == 1 && rowCount == 3) return 4;
return 2;
}
// Now diffY == 3
if (colCount == 4 && (whiteY == 0 || whiteY == rowCount - 1)) return 5;
return 3;
}
// The BFS algorithm for verification of the above function
function knightDistanceBfs(rowCount, colCount, whiteX, whiteY, blackX, blackY) {
let visited = new Set;
let frontier = [[whiteX, whiteY]];
visited.add(whiteX + whiteY * colCount);
let steps = 0;
while (frontier.length) {
let newFrontier = [];
for (let [whiteX, whiteY] of frontier) {
if (whiteX == blackX && whiteY == blackY) return steps;
for (let [dx, dy] of [[-2, -1], [2, -1], [2, 1], [-2, 1], [-1, -2], [1, -2], [1, 2], [-1, 2]]) {
let newX = whiteX + dx;
let newY = whiteY + dy;
if (newX < 0 || newY < 0 || newX >= colCount || newY >= rowCount) continue;
let key = newX + newY * colCount;
if (visited.has(key)) continue;
visited.add(key);
newFrontier.push([newX, newY]);
}
}
steps++;
frontier = newFrontier;
}
return -1;
}
// Quick test of all possibilities on boards with at most 5 rows and 5 columns:
for (let rowCount = 1; rowCount <= 5; rowCount++) {
for (let colCount = 1; colCount <= 5; colCount++) {
for (let whiteX = 0; whiteX < colCount; whiteX++) {
for (let whiteY = 0; whiteY < rowCount; whiteY++) {
for (let blackX = 0; blackX < colCount; blackX++) {
for (let blackY = 0; blackY < rowCount; blackY++) {
let answer = knightDistanceBfs(rowCount, colCount, whiteX, whiteY, blackX, blackY);
let answer2 = knightDistance(rowCount, colCount, whiteX, whiteY, blackX, blackY);
if (answer !== answer2) {
console.log({rowCount, colCount, whiteX, whiteY, blackX, blackY});
throw "Test case failed";
}
}
}
}
}
}
}
// I/O handling
let [rowInput, colInput] = document.querySelectorAll("input");
let table = document.querySelector("table");
let outputs = document.querySelectorAll("span");
let whiteX, whiteY, blackX, blackY;
rowInput.oninput = colInput.oninput = function () {
// Create table
table.innerHTML = "";
for (let i = +rowInput.value; i > 0; i--) {
let row = table.insertRow();
for (let j = +colInput.value; j > 0; j--) {
row.insertCell();
}
}
whiteX = -1;
blackX = -1;
};
table.onclick = function (e) {
if (e.target.tagName != "TD") return;
let x = e.target.cellIndex;
let y = e.target.parentNode.rowIndex;
if (x == whiteX && y == whiteY) {
e.target.textContent = "";
whiteX = -1;
whiteY = -1;
} else if (x == blackX && y == blackY) {
e.target.textContent = "";
blackX = -1;
blackY = -1;
} else if (whiteX == -1) {
e.target.textContent = "♘";
whiteX = x;
whiteY = y;
} else {
if (blackX != -1) { // Remove black piece first
table.rows[blackY].cells[blackX].textContent = "";
}
e.target.textContent = "♞";
blackX = x;
blackY = y;
}
if (blackX != -1 && whiteX != -1) {
outputs[0].textContent = knightDistanceBfs(+rowInput.value, +colInput.value, whiteX, whiteY, blackX, blackY);
outputs[1].textContent = knightDistance(+rowInput.value, +colInput.value, whiteX, whiteY, blackX, blackY);
} else {
outputs[0].textContent = outputs[1].textContent = "--";
}
}
rowInput.oninput();
table { border-collapse: collapse; cursor: pointer; margin: 2px }
td { border: 1px solid; width: 22px; height: 22px; padding: 0 }
input { width: 3em }
<div>Rows: <input id="rows" type="number" value="3"> Columns: <input id="cols" type="number" value="3"></div>
<table></table>
Number of moves: <span>--</span> (with BFS: <span>--</span>)
<div>Click on the board to place/remove pieces</div>
This would seem to be the basic logic you want, where ?_locs is a set of the locations a particular knight can be in (initialized to its initial location) and one_move yields a set of the locations that can be reached in 1 move from one of the locations in the argument:
while bk_locs intersect wh_locs is empty:
bk_locs = one_move(bk_locs)
wh_locs = one_move(wh_locs)
What this doesn't handle is counting moves (trivial) or identifying when to give up (harder).
This question already has answers here:
minimum number of steps to reduce number to 1
(10 answers)
Closed 6 years ago.
I am working on a code challenge now. My solution got "time exceed" even I have optimized it. I am seeking for help about more efficient solution or optimizing my solution a step more.
The description of the problem is :
Write a function which takes a positive integer as a string and returns the minimum number of operations needed to transform the number to 1. The number is up to 309 digits long, so there won't too many character than you can express in that many digits.
The transform process is limited to three operations:
1. Add 1
2. Subtract 1
3. Divide the number by 2 (only even number allow here)
My idea is to use DFS to traverse all possible solution with memorization to speed it up. But it does exceed the time limitation. The problem can not use dp because dp require a very large array to memorize. Below is my code:
private static int dfs(String num, int step,Map<String,Integer> memory){
if(num.equals("1")){
return step;
}
Integer size = memory.get(num);
if(size != null && size < step){
return Integer.MAX_VALUE;
}
memory.put(num, step);
int min = Integer.MAX_VALUE;
int lastDigit = num.charAt(num.length() - 1) - '0';
if(lastDigit % 2 == 0){
min = Math.min(min, dfs(divideBy2(num), step + 1, memory));
}else{
min = Math.min(min, dfs(divideBy2(num), step + 2, memory));
min = Math.min(min, dfs(divideBy2(plusOne(num)), step + 2, memory));
}
return min;
}
private static String plusOne(String num){
StringBuilder sb = new StringBuilder();
int carry = 1;
for(int i = num.length() - 1; i >=0; i--){
int d = (carry + num.charAt(i) - '0') % 10;
carry = (carry + num.charAt(i) - '0') / 10;
sb.insert(0, d);
}
if(carry == 1){
sb.insert(0, carry);
}
return sb.toString();
}
private static String divideBy2(String num){
StringBuilder sb = new StringBuilder();
int x = 0;
for(int i = 0; i < num.length(); i++){
int d = (x * 10 + num.charAt(i) - '0') / 2 ;
x = (num.charAt(i) - '0') % 2 ;
if( i > 0 || (i == 0 && d != 0))
sb.append(d);
}
return sb.toString();
}
Note: After test several cases: I got some sense but can not generalize the rule.
If the current number is odd. we got two choices here: plus 1 or subtract 1. The number after the operation can be divided by 2 more times, the steps will be shorter.
Update: Hi, guys, I work all the night and find a solution to pass the test. The idea is divide the problem into 2 sub-problem: 1. if the number is even, just divide it by two. 2. if the number is odd, choose the way let the number has more tailing zeros in its bit representation. I will explain more about the odd situation: if the number is odd, the last two bit can be "01" or "11". When it is "01", decrease it by 1 , which let the last two bit become to "00". If it is "11", increase it by 1, which generate "00". By doing this, the next even number generated by the odd number can be divided more times, which is really fast in practice. Below is my code, if you have some questions about the implementation, feel free to send me a message:
public static int answer(String n) {
// Your code goes here.
int count = 0;
while(!n.equals("1")){
if((n.charAt(n.length() - 1) - '0') % 2 == 0){
n = divideBy2(n);
}else if(n.equals("3") || lastTwoBit(n)){
n = subtractOne(n);
}else{
n = plusOne(n);
}
count++;
}
return count;
}
private static boolean lastTwoBit(String num){
int n = -1;
if(num.length() == 1){
n = Integer.valueOf(num);
}else{
n = Integer.valueOf(num.substring(num.length() - 2, num.length()));
}
if(((n >>> 1) & 1) == 0){
return true;
}
return false;
}
private static String subtractOne(String num){
if(num.equals("1")){
return "0";
}
StringBuilder sb = new StringBuilder();
int carry = -1;
for(int i = num.length() - 1; i >= 0; i--){
int d = carry + num.charAt(i) - '0';
if(d < 0){
carry = -1;
sb.insert(0, '9');
}else if((d == 0 && i != 0) || d > 0){
carry = 0;
sb.insert(0, d );
}
}
return sb.toString();
}
private static String plusOne(String num){
StringBuilder sb = new StringBuilder();
int carry = 1;
int i = 0;
for(i = num.length() - 1; i >=0; i--){
if(carry == 0){
break;
}
int d = (carry + num.charAt(i) - '0') % 10;
carry = (carry + num.charAt(i) - '0') / 10;
sb.insert(0, d);
}
if(carry ==0){
sb.insert(0, num.substring(0, i + 1));
}
if(carry == 1){
sb.insert(0, carry);
}
return sb.toString();
}
private static String divideBy2(String num){
StringBuilder sb = new StringBuilder();
int x = 0;
for(int i = 0; i < num.length(); i++){
int d = (x * 10 + num.charAt(i) - '0') / 2 ;
x = (num.charAt(i) - '0') % 2 ;
if( i > 0 || (i == 0 && d != 0))
sb.append(d);
}
return sb.toString();
}
While not at 1...
if Odd... Subtract 1 => even
if Even.. Divide by 2.
just sum the ops and return.
e.g. 5593
5593 -1 = 5592 /2 = 2796 /2 = 1398 /2 = 699 -1 = 698 /2 = 349 -1 = 348 /2 = 174 /2 = 87 -1 = 86 /2 = 43 -1 = 42 /2 = 21 -1 = 20 /2 = 10 /2 = 5 -1 = 4 /2 = 2 /2 = 1
19 Operations -///-/-//-/-/-//-//
Edit: Time complexity is O(logN) for we divide the number by two / subtract and then divide.
and Space is O(1)
public int make1(string s)
{
int n = 0;
while(s != "1")
{
switch(s[s.Length-1])
{
case '0':
case '2':
case '4':
case '6':
case '8':
s = div2(s);
++n;
break;
case '1':
case '3':
case '5':
case '7':
case '9':
s = minus1(s);
s = div2(s);
n += 2;
}
}
return n;
}
So I write a parallel coordinates program with Processing in my mac pro. However, I can't see any lines on the screen when I try to run this program. I am very confused because the program runs pretty well in my friend's windows based computer. I tried to add "noLoop()" in the end of my "draw()" function and it works. But I still can't figure out the reasons. Anyone knows the specific reason? Thanks in advance!
FloatTable data;
String dataPath = "cars.csv";
int numRows;
int numCols;
int[] colMin;
int[] colMax;
String[] colNames;
float plotX1, plotY1;
float plotX2, plotY2;
float diffBetweenXCoords;
PFont titleFont;
PFont labelFont;
PFont axisLimitsFont;
color[] axisColor = { #333333, #000000 };
color[] fontAxisColor = { #333333, #FF2222 };
color[] fontLimitsColor = { #555555, #FF2222 };
color triangleColor = #888888;
color[] linesColor = { #ED1317, #1397ED };
int[] axisOrder;
boolean[] axisFlipped;
// Setup
void setup()
{
size(1000, 500);
// Read data
data = new FloatTable(dataPath);
numRows = data.getRowCount();
numCols = data.getColumnCount();
colNames = data.getColumnNames();
colMin = new int[ numCols ];
colMax = new int[ numCols ];
axisOrder = new int[ numCols ];
axisFlipped = new boolean[ numCols ];
for(int col = 0; col < numCols; col++)
{
float maxNumber = data.getColumnMax(col);
float minNumber = data.getColumnMin(col);
colMin[col] = int(floor(minNumber));
colMax[col] = int(ceil(maxNumber));
axisOrder[col] = col;
axisFlipped[col] = false;
}
// Fonts
titleFont = createFont("Verdana", 16);
labelFont = createFont("Verdana Bold", 11);
axisLimitsFont = createFont("Georgia", 11);
// Plot area limits
plotX1 = 30;
plotX2 = width - plotX1;
plotY1 = 60;
plotY2 = height - plotY1;
diffBetweenXCoords = (plotX2 - plotX1) / (numCols - 1);
if(frame != null)
{
frame.setTitle(dataPath);
}
smooth();
}
// Draw
void draw()
{
// Background
background(240);
// Draw the plot area
fill(240);
noStroke();
rect(plotX1, plotY1, plotX2 - plotX1, plotY2 - plotY1);
//drawTitle();
drawAxis();
drawLines();
}
void drawAxis()
{
float xCoordsForAxis = plotX1;
float yAxisLbl = plotY2 + 40;
float yMinLbl = plotY2 + 15;
float yMaxLbl = plotY1 - 7;
float yTriMin = plotY1 - 25;
float yTriMax = plotY1 - 35;
strokeCap(PROJECT);
strokeWeight(1);
stroke(0);
for( int col = 0; col < numCols; col++, xCoordsForAxis += diffBetweenXCoords )
{
int colToDraw = axisOrder[col];
// Draw Axis
stroke(axisColor[0]);
line(xCoordsForAxis, plotY1, xCoordsForAxis, plotY2);
// Label min/max
textAlign(CENTER);
textFont(axisLimitsFont);
fill(fontLimitsColor[0]);
if( axisFlipped[colToDraw])
{
text( colMin[colToDraw], xCoordsForAxis, yMaxLbl);
text( colMax[colToDraw], xCoordsForAxis, yMinLbl);
}
else
{
text( colMin[colToDraw], xCoordsForAxis, yMinLbl);
text( colMax[colToDraw], xCoordsForAxis, yMaxLbl);
}
// Axis label
textFont( labelFont );
fill(fontAxisColor[0]);
text( colNames[colToDraw], xCoordsForAxis, yAxisLbl );
// Triangle
fill(triangleColor);
noStroke();
if( axisFlipped[colToDraw] )
{
triangle(xCoordsForAxis - 3, yTriMax, xCoordsForAxis, yTriMin, xCoordsForAxis + 3, yTriMax);
}
else
{
triangle(xCoordsForAxis - 3, yTriMin, xCoordsForAxis, yTriMax, xCoordsForAxis + 3, yTriMin);
}
}
}
void drawLines()
{
noFill();
strokeWeight(1);
for(int row = 0; row < numRows; row++)
{
beginShape();
for(int column = 0; column < numCols; column++)
{
int colToDraw = axisOrder[column];
if(data.isValid(row, column))
{
float cMax = ( axisFlipped[colToDraw] ? colMin[colToDraw] : colMax[colToDraw] );
float cMin = ( axisFlipped[colToDraw] ? colMax[colToDraw] : colMin[colToDraw] );
float value = data.getFloat(row, colToDraw);
float x = plotX1 + diffBetweenXCoords * colToDraw;
float y = map(value, cMin, cMax, plotY2, plotY1);
//stroke(#5679C1);
if(colToDraw == 0)
{
stroke( lerpColor(linesColor[0], linesColor[1], map(value, cMin, cMax, 0., 1.) ), 150 );
}
vertex(x, y);
}
}
endShape();
}
}
class FloatTable {
int rowCount;
int columnCount;
float[][] data;
String[] rowNames;
String[] columnNames;
FloatTable(String filename) {
String[] rows = loadStrings(filename);
String[] columns = split(rows[0], TAB);
columnNames = subset(columns, 1); // upper-left corner ignored
scrubQuotes(columnNames);
columnCount = columnNames.length;
rowNames = new String[rows.length-1];
data = new float[rows.length-1][];
// start reading at row 1, because the first row was only the column headers
for (int i = 1; i < rows.length; i++) {
if (trim(rows[i]).length() == 0) {
continue; // skip empty rows
}
if (rows[i].startsWith("#")) {
continue; // skip comment lines
}
// split the row on the tabs
String[] pieces = split(rows[i], TAB);
scrubQuotes(pieces);
// copy row title
rowNames[rowCount] = pieces[0];
// copy data into the table starting at pieces[1]
data[rowCount] = parseFloat(subset(pieces, 1));
// increment the number of valid rows found so far
rowCount++;
}
// resize the 'data' array as necessary
data = (float[][]) subset(data, 0, rowCount);
}
void scrubQuotes(String[] array) {
for (int i = 0; i < array.length; i++) {
if (array[i].length() > 2) {
// remove quotes at start and end, if present
if (array[i].startsWith("\"") && array[i].endsWith("\"")) {
array[i] = array[i].substring(1, array[i].length() - 1);
}
}
// make double quotes into single quotes
array[i] = array[i].replaceAll("\"\"", "\"");
}
}
int getRowCount() {
return rowCount;
}
String getRowName(int rowIndex) {
return rowNames[rowIndex];
}
String[] getRowNames() {
return rowNames;
}
// Find a row by its name, returns -1 if no row found.
// This will return the index of the first row with this name.
// A more efficient version of this function would put row names
// into a Hashtable (or HashMap) that would map to an integer for the row.
int getRowIndex(String name) {
for (int i = 0; i < rowCount; i++) {
if (rowNames[i].equals(name)) {
return i;
}
}
//println("No row named '" + name + "' was found");
return -1;
}
// technically, this only returns the number of columns
// in the very first row (which will be most accurate)
int getColumnCount() {
return columnCount;
}
String getColumnName(int colIndex) {
return columnNames[colIndex];
}
String[] getColumnNames() {
return columnNames;
}
float getFloat(int rowIndex, int col) {
// Remove the 'training wheels' section for greater efficiency
// It's included here to provide more useful error messages
// begin training wheels
if ((rowIndex < 0) || (rowIndex >= data.length)) {
throw new RuntimeException("There is no row " + rowIndex);
}
if ((col < 0) || (col >= data[rowIndex].length)) {
throw new RuntimeException("Row " + rowIndex + " does not have a column " + col);
}
// end training wheels
return data[rowIndex][col];
}
boolean isValid(int row, int col) {
if (row < 0) return false;
if (row >= rowCount) return false;
//if (col >= columnCount) return false;
if (col >= data[row].length) return false;
if (col < 0) return false;
return !Float.isNaN(data[row][col]);
}
float[] getColumnMinMax(int col) {
float Min = Float.MAX_VALUE;
float Max = -Float.MAX_VALUE;
for (int i = 0; i < rowCount; i++) {
if (!Float.isNaN(data[i][col])) {
if (data[i][col] < Min) {
Min = data[i][col];
}
if (data[i][col] > Max) {
Max = data[i][col];
}
}
}
float[] toRet = { Min, Max };
return toRet;
}
float getColumnMin(int col) {
float m = Float.MAX_VALUE;
for (int i = 0; i < rowCount; i++) {
if (!Float.isNaN(data[i][col])) {
if (data[i][col] < m) {
m = data[i][col];
}
}
}
return m;
}
float getColumnMax(int col) {
float m = -Float.MAX_VALUE;
for (int i = 0; i < rowCount; i++) {
if (isValid(i, col)) {
if (data[i][col] > m) {
m = data[i][col];
}
}
}
return m;
}
float getRowMin(int row) {
float m = Float.MAX_VALUE;
for (int i = 0; i < columnCount; i++) {
if (isValid(row, i)) {
if (data[row][i] < m) {
m = data[row][i];
}
}
}
return m;
}
float getRowMax(int row) {
float m = -Float.MAX_VALUE;
for (int i = 1; i < columnCount; i++) {
if (!Float.isNaN(data[row][i])) {
if (data[row][i] > m) {
m = data[row][i];
}
}
}
return m;
}
float getTableMin() {
float m = Float.MAX_VALUE;
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < columnCount; j++) {
if (isValid(i, j)) {
if (data[i][j] < m) {
m = data[i][j];
}
}
}
}
return m;
}
float getTableMax() {
float m = -Float.MAX_VALUE;
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < columnCount; j++) {
if (isValid(i, j)) {
if (data[i][j] > m) {
m = data[i][j];
}
}
}
}
return m;
}
}
When I tried to draw points rather than lines, it also works! Things become quite weird:)
Here are some lines in my .csv file:
make mpg cylinders displacement (cu in) horsepower weight (lb) acceleration (sec) year origin
chevrolet 18 8 307 130 3504 12 70 1
buick 15 8 350 165 3693 11.5 70 1
plymouth 18 8 318 150 3436 11 70 1
amc 16 8 304 150 3433 12 70 1
ford 17 8 302 140 3449 10.5 70 1
ford 15 8 429 198 4341 10 70 1
chevrolet 14 8 454 220 4354 9 70 1
plymouth 14 8 440 215 4312 8.5 70 1
pontiac 14 8 455 225 4425 10 70 1
amc 15 8 390 190 3850 8.5 70 1
dodge 15 8 383 170 3563 10 70 1
plymouth 14 8 340 160 3609 8 70 1
chevrolet 15 8 400 150 3761 9.5 70 1
buick 14 8 455 225 3086 10 70 1
toyota 24 4 113 95 2372 15 70 3
plymouth 22 6 198 95 2833 15.5 70 1
amc 18 6 199 97 2774 15.5 70 1
ford 21 6 200 85 2587 16 70 1
datsun 27 4 97 88 2130 14.5 70 3
volkswagen 26 4 97 46 1835 20.5 70 2
peugeot 25 4 110 87 2672 17.5 70 2
audi 24 4 107 90 2430 14.5 70 2
saab 25 4 104 95 2375 17.5 70 2
bmw 26 4 121 113 2234 12.5 70 2
What's the most efficient algorithm anyone can think of that, given a natural number n, returns the least natural number x with n positive divisors (including 1 and x)? For example, given 4 the algorithm should result in 6 (divisors: 1,2,3,6); i.e. 6 is the smallest number having 4 distinct factors. Similarly, given 6, the algorithm should result in 12 (divisors: 1,2,3,4,6,12); i.e. 12 is the smallest number having 6 distinct factors
In terms of real-world performance, I'm looking for a scalable algorithm which can give answers of the order of 1020 within 2 seconds on a machine which can do 107 computations per second.
http://www.primepuzzles.net/problems/prob_019.htm
b) Jud McCranie, T.W.A. Baumann & Enoch Haga sent basically the same
procedure to find N(d) for a given d:
Factorize d as a product of his prime divisors: d = p1a1 * p2a2 *p3a3 *...
convert this factorization in another arithmetically equivalent factorization, composed of non-powered monotonically decreasing and not
necesarilly prime factors... (uf!...) d = p1a1 * p2a2 *p3a3 *... =
b1 * b2 * b3... such that b1 ≥ b2 ≥ b3...
You must realize that for every given d, there are several
arithmetically equivalent factorizations that can be done: by example:
if d = 16 = 24 then there are 5 equivalent factorizations:
d = 2*2*2*2 = 4*2*2 = 4*4 = 8*2 = 16
N is the minimal number resulting of computing 2b1-1 * 3b2-1 * 5b3-1 * ... for all the equivalent factorizations of d. Working the same example:
N(16) = the minimal of these {2 * 3 * 5 * 7, 23 * 3 * 5, 23 * 33, 27 * 3, 215} = 23 * 3 * 5 = 120
Update: With numbers around 1020, pay attention to the notes by Christian Bau quoted on the same page.
//What is the smallest number with X factors?
function smallestNumberWithThisManyFactors(factorCount) {
Number.prototype.isPrime = function() {
let primeCandidate = this;
if(primeCandidate <= 1 || primeCandidate % 1 !== 0) return false
let i = 2;
while(i <= Math.floor(Math.sqrt(primeCandidate))){
if(primeCandidate%i === 0) return false;
i++;
}
return true;
}
Number.prototype.nextPrime = function() {
let currentPrime = this;
let nextPrimeCandidate = currentPrime + 1
while(nextPrimeCandidate < Infinity) {
if(nextPrimeCandidate.isPrime()){
return nextPrimeCandidate;
} else {
nextPrimeCandidate++;
}
}
}
Number.prototype.primeFactors = function() {
let factorParent = this;
let primeFactors = [];
let primeFactorCandidate = 2;
while(factorParent !== 1){
while(factorParent % primeFactorCandidate === 0){
primeFactors.push(primeFactorCandidate);
factorParent /= primeFactorCandidate;
}
primeFactorCandidate = primeFactorCandidate.nextPrime();
}
return primeFactors;
}
Number.prototype.factors = function() {
let parentNumber = this.valueOf();
let factors = []
let iterator = parentNumber % 2 === 0 ? 1 : 2
let factorCandidate = 1;
for(factorCandidate; factorCandidate <= Math.floor(parentNumber/2); factorCandidate += iterator) {
if(parentNumber % factorCandidate === 0) {
factors.push(factorCandidate)
}
}
factors.push(parentNumber)
return factors
}
Array.prototype.valueSort = function() {
return this.sort(function (a,b){ return a-b })
}
function clone3DArray(arrayOfArrays) {
let cloneArray = arrayOfArrays.map(function(arr) {
return arr.slice();
});
return cloneArray;
}
function does3DArrayContainArray(arrayOfArrays, array){
let aOA = clone3DArray(arrayOfArrays);
let a = array.slice(0);
for(let i=0; i<aOA.length; i++){
if(aOA[i].sort().join(',') === a.sort().join(',')){
return true;
}
}
return false;
}
function removeDuplicateArrays(combinations) {
let uniqueCombinations = []
for(let c = 0; c < combinations.length; c++){
if(!does3DArrayContainArray(uniqueCombinations, combinations[c])){
uniqueCombinations[uniqueCombinations.length] = combinations[c];
}
}
return uniqueCombinations;
}
function generateCombinations(parentArray) {
let generate = function(n, src, got, combinations) {
if(n === 0){
if(got.length > 0){
combinations[combinations.length] = got;
}
return;
}
for (let j=0; j<src.length; j++){
generate(n - 1, src.slice(j + 1), got.concat([src[j]]), combinations);
}
return;
}
let combinations = [];
for(let i=1; i<parentArray.length; i++){
generate(i, parentArray, [], combinations);
}
combinations.push(parentArray);
return combinations;
}
function generateCombinedFactorCombinations(primeFactors, primeFactorCombinations) {
let candidates = [];
for(let p=0; p<primeFactorCombinations.length; p++){
let product = 1;
let primeFactorsCopy = primeFactors.slice(0);
for(let q=0; q<primeFactorCombinations[p].length; q++){
product *= primeFactorCombinations[p][q];
primeFactorsCopy.splice(primeFactorsCopy.indexOf(primeFactorCombinations[p][q]), 1);
}
primeFactorsCopy.push(product);
candidates[candidates.length] = primeFactorsCopy.valueSort().reverse();
}
return candidates;
}
function determineMinimumCobination (candidates){
let minimumValue = Infinity;
let bestFactorCadidate = []
for(let y=0; y<candidates.length; y++){
let currentValue = 1;
let currentPrime = 2;
for(let z=0; z<combinedFactorCandidates[y].length; z++){
currentValue *= Math.pow(currentPrime,(combinedFactorCandidates[y][z])-1);
currentPrime = currentPrime.nextPrime();
}
if(currentValue < minimumValue){
minimumValue = currentValue;
bestFactorCadidate = combinedFactorCandidates[y];
}
}
return minimumValue;
}
let primeFactors = factorCount.primeFactors();
let primeFactorCombinations = removeDuplicateArrays(generateCombinations(primeFactors));
let combinedFactorCandidates = generateCombinedFactorCombinations(primeFactors, primeFactorCombinations);
let smallestNumberWithFactorCount = determineMinimumCobination(combinedFactorCandidates);
console.log('The smallest number with ' + factorCount + ' factors is: ')
console.log(smallestNumberWithFactorCount)
console.log('With these factors being: ')
console.log(smallestNumberWithFactorCount.factors())
return smallestNumberWithFactorCount;
}
smallestNumberWithThisManyFactors(10)
Question: given an integer number n, print the numbers from 1 up to n2 like this:
n = 4
result is:
01 02 03 04
12 13 14 05
11 16 15 06
10 09 08 07
How do you solve it (apart from the solution provided in the link below)?
http://www.programmersheaven.com/mb/CandCPP/81986/81986/problem-in-making-ap-c++-program/?S=B20000
I'm looking in another direction. So far, I'm trying to figure out if I could obtain the ordered list of positions I have to fill in.
Here's what Im looking into: is there a way to obtain the "fdisp" so as to solve the problem that way, instead of "walk" in the matrix?
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
n = len(matrix)
# final disposition wrote by hand: how to get it for arbitrary n?
fdisp = [(0,0), (0,1), (0,2), (0,3), (1,3), (2,3), (3,3), (3,2),
(3,1), (3,0), (2,0), (1,0), (1,1), (1,2), (2,2), (2,1)]
for val,i in enumerate(fdisp):
matrix[i[0]][i[1]] = val + 1
def show_matrix(matrix, n):
for i,l in enumerate(matrix):
for j in range(n):
print "%d\t" % matrix[i][j],
print
show_matrix(matrix, n)
Here's a different approach. It relies on spotting that the movements you make cycle between: right, down, left, up, right, .... Further, the number of times you move goes: 3 right, 3 down, 3 left, 2 up, 2 right, 1 down, 1 left. So without further ado, I will code this up in Python.
First, I will use some itertools and some numpy:
from itertools import chain, cycle, imap, izip, repeat
from numpy import array
The directions cycle between: right, down, left, up, right, ...:
directions = cycle(array(v) for v in ((0,1),(1,0),(0,-1),(-1,0)))
(I'm using numpy's arrays here so I can easily add directions together. Tuples don't add nicely.)
Next, the number of times I move counts down from n-1 to 1, repeating each number twice, and the first number three times:
countdown = chain((n-1,), *imap(repeat, range(n-1,0,-1), repeat(2)))
So now my sequence of directions can be created by repeating each successive direction by the paired number in countdown:
dirseq = chain(*imap(repeat, directions, countdown))
To get my sequence of indices, I can just sum this sequence, but (AFAIK) Python does not provide such a method, so let's quickly throw one together:
def sumseq(seq, start=0):
v = start
yield v
for s in seq:
v += s
yield v
Now to generate the original array, I can do the following:
a = array(((0,)*n,)*n) # n-by-n array of zeroes
for i, v in enumerate(sumseq(dirseq, array((0,0)))):
a[v[0], v[1]] = i+1
print a
Which, for n = 4, gives:
[[ 1 2 3 4]
[12 13 14 5]
[11 16 15 6]
[10 9 8 7]]
and, for n = 5, gives:
[[ 1 2 3 4 5]
[16 17 18 19 6]
[15 24 25 20 7]
[14 23 22 21 8]
[13 12 11 10 9]]
This approach can be generalised to rectangular grids; I leave this as an exercise for the reader ;)
Though your example is in python and this is in Java, I think you should be able to follow the logic:
public class SquareTest {
public static void main(String[] args) {
SquareTest squareTest = new SquareTest(4);
System.out.println(squareTest);
}
private int squareSize;
private int[][] numberSquare;
private int currentX;
private int currentY;
private Direction currentDirection;
private enum Direction {
LEFT_TO_RIGHT, RIGHT_TO_LEFT, TOP_TO_BOTTOM, BOTTOM_TO_TOP;
};
public SquareTest(int squareSize) {
this.squareSize = squareSize;
numberSquare = new int[squareSize][squareSize];
currentY = 0;
currentX = 0;
currentDirection = Direction.LEFT_TO_RIGHT;
constructSquare();
}
private void constructSquare() {
for (int i = 0; i < squareSize * squareSize; i = i + 1) {
numberSquare[currentY][currentX] = i + 1;
if (Direction.LEFT_TO_RIGHT.equals(currentDirection)) {
travelLeftToRight();
} else if (Direction.RIGHT_TO_LEFT.equals(currentDirection)) {
travelRightToLeft();
} else if (Direction.TOP_TO_BOTTOM.equals(currentDirection)) {
travelTopToBottom();
} else {
travelBottomToTop();
}
}
}
private void travelLeftToRight() {
if (currentX + 1 == squareSize || numberSquare[currentY][currentX + 1] != 0) {
currentY = currentY + 1;
currentDirection = Direction.TOP_TO_BOTTOM;
} else {
currentX = currentX + 1;
}
}
private void travelRightToLeft() {
if (currentX - 1 < 0 || numberSquare[currentY][currentX - 1] != 0) {
currentY = currentY - 1;
currentDirection = Direction.BOTTOM_TO_TOP;
} else {
currentX = currentX - 1;
}
}
private void travelTopToBottom() {
if (currentY + 1 == squareSize || numberSquare[currentY + 1][currentX] != 0) {
currentX = currentX - 1;
currentDirection = Direction.RIGHT_TO_LEFT;
} else {
currentY = currentY + 1;
}
}
private void travelBottomToTop() {
if (currentY - 1 < 0 || numberSquare[currentY - 1][currentX] != 0) {
currentX = currentX + 1;
currentDirection = Direction.LEFT_TO_RIGHT;
} else {
currentY = currentY - 1;
}
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < squareSize; i = i + 1) {
for (int j = 0; j < squareSize; j = j + 1) {
builder.append(numberSquare[i][j]);
builder.append(" ");
}
builder.append("\n");
}
return builder.toString();
}
}
Another way to do it, this time in C#:
int number = 9;
var position = new { x = -1, y = 0 };
var directions = new [] {
new { x = 1, y = 0 },
new { x = 0, y = 1 },
new { x = -1, y = 0 },
new { x = 0, y = -1 }
};
var sequence = (
from n in Enumerable.Range(1, number)
from o in Enumerable.Repeat(n, n != number ? 2 : 1)
select o
).Reverse().ToList();
var result = new int[number,number];
for (int i = 0, current = 1; i < sequence.Count; i++)
{
var direction = directions[i % directions.Length];
for (int j = 0; j < sequence[i]; j++, current++)
{
position = new {
x = position.x + direction.x,
y = position.y + direction.y
};
result[position.y, position.x] = current;
}
}
I found a way. Now I've to improve it a bit, especially I've to find a cleaner way to build "fdisp".
n = 5
dim = n
pos = (0, -1)
fdisp = []
squares = n % 2 == 0 and n / 2 or n / 2 + 1
for _ in range(squares):
pos = (pos[0], pos[1] + 1)
fdisp.append(pos)
fdisp += [(pos[0],pos[1]+i) for i in range(1, dim)]
pos = fdisp[-1]
fdisp += [(pos[0]+i,pos[1]) for i in range(1, dim)]
pos = fdisp[-1]
fdisp += [(pos[0],pos[1]-i) for i in range(1, dim)]
pos = fdisp[-1]
fdisp += [(pos[0]-i,pos[1]) for i in range(1, dim - 1)]
pos = fdisp[-1]
dim = dim - 2
matrix = [[0] * n for i in range(n)]
for val,i in enumerate(fdisp):
matrix[i[0]][i[1]] = val + 1
def show_matrix(matrix, n):
for i,l in enumerate(matrix):
for j in range(n):
print "%d\t" % matrix[i][j],
print
show_matrix(matrix, n)
I have solved your problem using C++. I don't know if it will be helpful for you. But posting it. If it works for you it will be a pleasure.
Here is the Code:
#include<iostream>
#include<string.h>
using namespace std;
bool valid(int n,int r,int c)
{
if(r>=1 && r<=n && c>=1 && c<=n)
return true;
return false;
}
int main()
{
pair<int,int>d1,d2,d3,d4,temp;
d1 = make_pair(0,1);
d2 = make_pair(1,0);
d3 = make_pair(0,-1);
d4 = make_pair(-1,0);
/**********************direction******************************/
int n, i, j, counter=1, newR = 1, newC = 0, direction = 4;
bool changeDir=true;
/**************************variables*************************/
cin>>n;
int arr[n+1][n+1];
int visited[n+1][n+1];
/*************************arrays********************************/
memset(visited,0,sizeof(visited));
memset(arr,0,sizeof(arr));
/***************initializing the array**************************/
while(counter<=n*n)
{
if(direction==1 && changeDir)
{
temp = make_pair(d2.first,d2.second);
direction=2;
changeDir=false;
}
else if(direction==2&& changeDir)
{
temp = make_pair(d3.first,d3.second);
direction=3;
changeDir=false;
}
else if(direction==3&& changeDir)
{
temp = make_pair(d4.first,d4.second);
direction=4;
changeDir=false;
}
else if(direction==4&& changeDir)
{
temp = make_pair(d1.first,d1.second);
direction=1;
changeDir=false;
}
while(counter<=(n*n) && !changeDir)
{
newR =newR+temp.first;
newC=newC+temp.second;
if(valid(n,newR,newC) && !visited[newR][newC])
{
arr[newR][newC]=counter;
visited[newR][newC]=1;
counter++;
}
else
{
newR-=temp.first;
newC-=temp.second;
changeDir=true;
break;
}
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(arr[i][j]<10)
cout<<0;
cout<<arr[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
Here is the output where N=5:
01 02 03 04 05
16 17 18 19 06
15 24 25 20 07
14 23 22 21 08
13 12 11 10 09
Thank you.