Do C++ and Python write to disk differently? - python

So, a few years ago I wrote a program in Python that writes the English names of a sequential list of numbers to a file (one, two, three, etc.). I have been working on getting a C++ version working off and on for the last month (personal project), and I think I have it running pretty well. One problem: it's five times slower than the Python version. I've tried switching string concatenation methods ( << vs operator+ vs operator+= vs .append()), using fprinf() instead of ofstream, pre-allocating the string size (.reserve()), and a lot of other things I can't remember, but I seemed to have run into a wall. Then I noticed that the C++ writing speed seems to max out around 70MB/s, whereas the Python version writes at around 350MB/s. The drive I am using is a 5400rpm disk (CrystalDiskMark gives a sequential write speed of 60-90 MB/s), so the C++ write speeds are believable, but the Python?
TL;DR: Python seems to be writing five times faster than possible, (near to the read speeds!) of the disk.
I've included the programs below, in case I am missing something obvious (plausible). "Benchmarking" involved running each program for the numbers 1-1,000,000, resulting in a file of 50,824KB. ~50s for C++, ~8.5s for Python.
Python:
##Code in Python version 2.7.5 for generating a file with the English names of a set range of numbers.
while 1:
s=input("Starting_Value:")
f=input("Ending_Value:")
filename=raw_input("Desired Name of File:")
##dictionary
one=["","one","two","three","four","five","six","seven","eight","nine","error_one"]
one2=["","-one","-two","-three","-four","-five","-six","-seven","-eight","-nine","error_one2"]
teen=["ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen","error_teen"]
ten=["","twenty","thirty","fourty","fifty","sixty","seventy","eighty","ninety","error_ten"]
##Functions
def translate(n): ##handles '' to 999
work=[]
if n>=100:
work.append(one[int(n/100)]+" hundred ")
n=n-(100*int(n/100))
if n>=10:
if n>=20:
work.append(ten[int(n/10)-1]+one2[n-(10*int(n/10))]+" ")
else:
work.append(teen[n%10]+" ")
elif n>=1:
work.append(one[n]+ " ")
elif n>=10:
if n>=20:
work.append(ten[int(n/10)-1]+one2[n-(10*int(n/10))]+" ")
else:
work.append(teen[n%10]+" ")
elif n>=1:
work.append(str(one[n])+" ")
end1=', '.join(work)
end1=end1.replace(", ","")
return end1
def english(m): ##handles billions, hundred millions, millions, hundred thousands, thousands
work2=[]
if m>=1000000000:
work2.append(str(translate(int(m/1000000000)))+"billion ")
elif m>=1000000:
work2.append(str(translate(int(m/1000000)))+"million "+str(translate(int(m-(1000000*int(m/1000000)))/1000))+"thousand "+str(translate(m-(1000*int(m/1000)))))
if ((int(m/1000)%1000)==0):
end3=str(', '.join(work2))
end4=end3.replace("thousand ", "")
work2[:]=[]
work2=[str(end4)]
else:
end3=str()
elif m>=1000:
work2.append(str(translate(int(m/1000)))+"thousand "+str(translate(m%1000)))
elif m>=1:
work2.append(translate(m))
end2=str(', '.join(work2))
end2=end2[:-1]
return end2
##Main Program - Iterator
file = open(str(filename), "a")
for i in range(f-s+1):
file.write(str(english(s))+", ")
s = s + 1
file.close()
a = raw_input("Close window to EXIT, or press ENTER to generate another file")
C++
//Generates a file of sequential numbers in English
//libraries
#include <iostream> //for output to terminal
#include <fstream> //for output to file
#include <string> //for handling strings
using namespace std; //yes
ofstream fout; //for convenience with 'cout'
//function prototypes
string thousands(int n); //translates 1 to 999
string millions(int m); //translates the hundred thousands, millions,
hundred millions
int lint(int j, int k); //outputs the digits of a number greater than the kth place i.e. lint(123456, 1000) = 123
//variables
int shi = 0; //starting value
int kut = 1; //ending value
int i = 0; //iterator
string fname = ""; //filename
string buffern = ""; //buffer for thousands
string bufferm = ""; //buffer for millions
string bufferf = ""; //first digit buffer
//dictionary
char one[10][7] = { ""," one"," two"," three"," four"," five"," six"," seven"," eight"," nine" };
char one2[10][7] = { "","-one","-two","-three","-four","-five","-six","-seven","-eight","-nine" };
char teen[10][11] = { " ten"," eleven"," twelve"," thirteen"," fourteen"," fifteen"," sixteen"," seventeen"," eighteen"," nineteen" };
char ten[10][9] = { "",""," twenty"," thirty"," fourty"," fifty"," sixty"," seventy"," eighty"," ninety" };
//main function
int main()
{
while (1)
{
//get user input
cout << " Starting Number: ";
cin >> shi;
cout << " Ending Number: ";
cin >> kut;
while (fout.is_open() != 1)
{
cout << " Desired Filename: ";
cin >> fname;
fname.append(".txt");
fout.open(fname);
if (fout.is_open() != 1)
cout << "\n Invalid file name. Please try again.\n";
}
//translate and write to file
if (shi == 0) { //handles starting at zero
fout << "zero,";
shi = 1;
}
else //handles spacing for next word
{
bufferf = millions(shi);
bufferf.erase(0, 1);
bufferf += ",";
fout << bufferf;
shi++;
}
for (i = shi; i < (kut); ++i) //Main Iterator
{
fout << millions(i) << ",";
}
fout << millions(kut) << "."; //handles last word
fout.close();
//display confirmation and prompt to exit/continue
cout << "\n Complete\n";
cin.get();
cin.ignore();
cout << endl;
}
}
//function definitions
string thousands(int n) //writes '' to 999
{
buffern = "";
buffern.reserve(30);
if (n >= 100) { //write hundreds place
buffern += one[lint(n, 100)];
buffern += " hundred";
n = n % 100;
if (n >= 10) { //write tens place
if (n >= 20) {
buffern += ten[lint(n, 10)];
buffern += one2[n % 10];
}
else { //deal with 'teens'
buffern += teen[n % 10];
}
}
else if (n >= 1) { //write ones place
buffern += one[n % 10];
}
}
else if (n >= 10) { //write tens place
if (n >= 20) {
buffern += ten[lint(n, 10)];
buffern += one2[n % 10];
}
else { //deal with 'teens'
buffern += teen[n % 10];
}
}
else if (n >= 1) { //write ones place
buffern += one[n];
}
return buffern;
}
string millions(int m)
{
bufferm = "";
bufferm.reserve(100);
if (m >= 1000000)
{
if (int(m / 1000) % 1000 == 0) { //if xxx,000,xxx
bufferm += thousands(lint(m, 1000000));
bufferm += " million";
bufferm += thousands(m % 1000);
}
else {
bufferm += thousands(lint(m, 1000000)); //millions
bufferm += " million";
bufferm += thousands(lint(m, 1000) % 1000); //hundred thousands
bufferm += " thousand";
bufferm += thousands(m % 1000); //thousands
}
}
else if (m >= 1000) {
bufferm += thousands(lint(m, 1000)); //hundred thousands
bufferm += " thousand";
bufferm += thousands(m % 1000); //thousands
}
else if (m >= 1) {
bufferm += thousands(m); //thousands
}
return bufferm;
}
int lint(int j, int k)
{
return ((j - (j % k)) / k);
}
I would appreciate any insights as to why the programs are running at different speeds, how the Python is writing so fast, or suggestions on speeding up the c++ code.
Edit: #VTT was right, not all of the C++ code was there. Added.

Related

Convert typedef struct from C++ to Python

I'm trying to port the following series of videos from C++ to Python.
You can find them in YT: https://www.youtube.com/channel/UCzGKCXSeHjDRSmpX9SmQ1fw/videos
The library with the 12000 words can be found here: https://pastebin.com/E5sDrFJ5
The idea behing is to build a solver for crosswords from scratch. So far, up to module 9, my Python code is equivalent to the C++ version:
def ToUpper(s):
return s.upper()
class Library:
def __init__(self):
self.words = []
self.counts = {}
def IsWord(self, s):
for w in self.words:
if s == w:
return True
return False
def GetWord(self, i):
assert (i >= 0 and i < len(self.words))
return self.words[i]
def ReadFromFile(self, filename):
with open(filename, 'r') as f:
for line in f:
# print(f"{line.rstrip()} ({len(line.rstrip())})")
line = ToUpper(line)
self.words.append(line.rstrip())
print(f"Read {len(self.words)} words from file '{filename}'")
def ComputeStats(self):
assert self.counts == {}
for i in range(18):
self.counts[i] = []
for s in self.words:
_len = len(s)
if _len < 18:
self.counts[_len].append(_len)
def PrintStats(self):
print("Here are the counts of each word length")
for k,v in self.counts.items():
if k != 0:
print(f"[{k}] {len(v)}")
class Grid:
def __init__(self, n):
self.name = n
self.lines = []
def rows(self):
return len(self.lines)
def cols(self):
if self.lines == []:
return 0
else:
return len(self.lines[0])
def LoadFromFile(self, filename):
with open(filename, 'r') as f:
for line in f:
# print(f"{line.rstrip()} ({len(line.rstrip())})")
if not line.startswith('#'):
self.lines.append(line.rstrip())
def Check(self):
for s in self.lines:
assert len(s) == self.cols()
def Print(self):
print(f"Grid: {self.name} "
f"(rows={self.rows()},"
f" cols={self.cols()})")
for s in self.lines:
print(f" {s.rstrip()}")
if __name__ == "__main__":
lib = Library()
lib.ReadFromFile("top_12000.txt")
lib.ComputeStats()
lib.PrintStats()
print(lib.IsWord("DOG"))
print(lib.IsWord("FUFFJFJ"))
print(lib.IsWord("THANKS"))
# grid = Grid("MY GRID")
# grid.LoadFromFile('test')
# grid.Check()
# grid.Print()
The C++ version from the video is this one:
#include <iostream>
#include <string>
#include <vector>
#include <assert.h>
#include <fstream>
using namespace std;
string ToUpper(string s) {
string s2;
for (char c : s) {
s2.push_back(toupper(c));
}
return s2;
}
class Library {
public:
bool IsWord(string s) const {
for (string t : words) {
if (s == t) {
return true;
}
}
return false;
}
void ComputeStats() {
assert(counts.empty());
counts.resize(18);
for (string s : words) {
int len = s.length();
if (len < 18) {
counts[len]++;
}
}
}
void PrintStats() const {
cout << "Here are the counts of each word length:\n";
for (int i=1; i<counts.size(); i++) {
cout << "[" << i << "] " << counts[i] << "\n";
}
}
string GetWord(int i) const {
assert(i >= 0 && i < words.size());
return words[i];
}
void ReadFromFile(string filename) {
ifstream f;
f.open(filename);
while (!f.eof()) {
string line;
getline(f, line);
// cout << line << " (" << line.length() << ")\n";
if (!line.empty()) {
line = ToUpper(line);
int len = line.length();
if (line[len-1] == '\r') {
line = line.substr(0, len-1);
}
words.push_back(line);
}
}
cout << "Read " << words.size() << " words from file '"
<< filename << "'\n";
}
private:
vector<string> words;
vector<int> counts;
};
struct Grid {
Grid(string n) {
name = n;
}
int rows() const { return lines.size(); }
int cols() const {
if (lines.empty()) {
return 0;
} else {
return lines[0].size();
}
}
void LoadFromFile(string filename) {
ifstream f;
f.open(filename);
while (!f.eof()) {
string line;
getline(f, line);
cout << line << " (" << line.length() << ")\n";
if (!line.empty() && line[0] != '#') {
lines.push_back(line);
}
}
}
void Check() const {
for (int i=0; i<lines.size(); i++) {
assert(lines[i].size() == cols());
}
}
void Print() const {
cout << "Grid: " << name
<< " (rows=" << rows()
<< ", cols=" << cols() << ")\n";
for (string s : lines) {
cout << " " << s << "\n";
}
}
string name;
vector<string> lines;
};
int main() {
Library lib;
lib.ReadFromFile("top_12000.txt");
lib.ComputeStats();
lib.PrintStats();
cout << lib.IsWord("DOG") << "\n";
cout << lib.IsWord("FUFFJFJ") << "\n";
cout << lib.IsWord("THANKS") << "\n";
// Grid grid("MY GRID");
// grid.LoadFromFile("test");
// grid.Check();
// grid.Print();
But I got stuck in lesson 9 because there is no "struct" data type in Python. In the video for lesson 9, this new structure "Word" was introduced. I highligthed the changes:
**struct Word {
Word(string s) {
word = s;
}
string word;
};
typedef vector<Word> Words;**
class Library {
public:
bool IsWord(string s) const {
for (**Word w** : words) {
if (s == **w.word**) {
return true;
}
}
return false;
}
void ComputeStats() {
assert(counts.empty());
counts.resize(18);
for (**Word w** : words) {
int len = **w.word**.length();
if (len < 18) {
counts[len]++;
}
}
}
void PrintStats() const {
cout << "Here are the counts of each word length:\n";
for (int i=1; i<counts.size(); i++) {
cout << "[" << i << "] " << counts[i] << "\n";
}
}
string GetWord(int i) const {
assert(i >= 0 && i < words.size());
return words[i]**.word**;
}
void ReadFromFile(string filename) {
ifstream f;
f.open(filename);
while (!f.eof()) {
string line;
getline(f, line);
// cout << line << " (" << line.length() << ")\n";
if (!line.empty()) {
line = ToUpper(line);
int len = line.length();
if (line[len-1] == '\r') {
line = line.substr(0, len-1);
}
words.push_back(**Word(line)**);
}
}
cout << "Read " << words.size() << " words from file '"
<< filename << "'\n";
}
private:
**Words words**;
vector<int> counts;
}
How should I proceed? Is it just to create a class "Word" like this?
class Word:
def __init__(self, n):
self.word = n
I'm missing the typedef, because there are not such structures in Python. And then, how to use this new class in the "Library" class?
class Library:
def __init__(self):
self.words = Words()
self.counts = {}
Because this is giving me a TypeError:
TypeError: __init__() missing 1 required positional argument: 'n'
Any help will be appreciated.

Own array-implementation in Python

I was able to create my own class in C++ which is basically an array of fixed size, where I can append, retrieve, and change integers in.
This is the C++-code:
#include <iostream>
class List {
public:
//Item-object needed to store
//elements
struct Item {
int data = 0;
Item* next = nullptr;
};
//Constructor
//creates a list of fixed size
List(int size) {
//Filling up with empty items
for (int i = 0; i < size; i++) {
Item* item = new Item;
//If first item,
//store start-address
//set buffer to start address
if (i == 0)
this->start = item;
//Setting current item as nextptr
//for previous item in buffer
if (i > 0)
this->buffer->next = item;
//Storing current address in buffer
this->buffer = item;
//Outputting address and value (just for testing purposes)
//std::cout << "Address: " << &item << " -> " << item->data << std::endl;
}
}
//Destructor
~List() {
Item* current = this->start;
while(current) {
delete current;
current = current->next;
}
}
//Returns address of very first element in list
Item* getFirstItemAddress() {
return this->start;
}
//Append to list
bool append(int value) {
Item* start = this->start;
//Calculating insertIndex
int insertIndex = this->index *2;
//Inserting
(start + insertIndex)->data = value;
//Increment index for next call
this->index++;
return true;
}
//Retrieve item at index from list
int retrieve(int i) {
//Error check (index out of range)
if (i >= this->index) {
std::cerr << "Index out of range!" << std::endl;
throw("Index out of range");
return -1;
}
i = i * 2;
return (start + i)->data;
}
//Remove element at index from list
bool remove(int index) {
index = index * 2;
//Shifting all elements above 'index'
//one down
Item* current = (this->start + index);
while (current->next) {
Item* next = current->next;
current->data = next->data;
current = next;
}
//Decrementing index
this->index--;
return true;
}
//Change element to value at index
bool change(int index, int value) {
index = index * 2;
(this->start + index)->data = value;
return true;
}
//Printing out list
void print() {
int counter = 0;
Item* current = this->getFirstItemAddress();
while (current) {
if (counter >= this->index) break;
std::cout << current->data << std::endl;
current = current->next;
counter++;
}
}
private:
//Holding address of first item
Item* start = nullptr;
//Buffer holding temporary address
Item* buffer = nullptr;
//Variable pointing to indexToInsert
int index = 0;
};
int main() {
List list(5);
//Printing out
/*std::cout << std::endl << "Testing output:" << std::endl;
List::Item* current = list.getFirstItemAddress();
while (current) {
std::cout << current->data << std::endl;
current = current->next;
}*/
List::Item* start = list.getFirstItemAddress();
list.append(1);
list.append(2);
list.append(3);
list.append(4);
list.append(5);
std::cout << list.retrieve(0) << std::endl;
std::cout << list.retrieve(1) << std::endl;
std::cout << list.retrieve(2) << std::endl;
std::cout << list.retrieve(3) << std::endl;
std::cout << list.retrieve(4) << std::endl;
list.remove(2);
std::cout << std::endl;
list.print();
std::cout << std::endl;
list.change(3, 8);
std::cout << list.retrieve(3) << std::endl;
return 0;
}
But I actually want it in Python 3,
Python Code:
class Item:
data = None
next = None
def __init__(self, data=None, next=None):
self.data = data
self.next = next
class List:
start = Item()
buffer = Item()
index = 0
def __init__(self, size):
for i in range(0, size):
item = Item
if (i == 0):
start = item
if (i > 0):
self.buffer.next = item
buffer = item
def getFirstItemAddress(self):
return self.start
def append(self, value):
start = self.start
insertIndex = self.index * 2
(addressof(start) + insertIndex).data = value
self.index+=1
return True
def retrieve(self, i):
if i >= self.index:
print("Index out of range")
return -1
exit()
i = i * 2
return (self.start + i).data
def remove(self, index):
index = index * 2
current = (self.start + index)
while current.next:
next = current.next
current.data = next.data
current = next
self.index-=1
return True
def print(self):
counter = 0
current = self.getFirstItemAddress()
while current:
if counter >= self.index: break
print(current.data)
current = current.next
counter+=1
list = List(5)
list.append(1)
That code ain't working a little bit. I get errors like:
Traceback (most recent call last):
File "main.py", line 73, in <module>
list.append(1)
File "main.py", line 34, in append
(start + insertIndex).data = value
TypeError: unsupported operand type(s) for +: 'Item' and 'int'
Which is pretty logic, however, I need to be able to use SOME KIND of pointers and references in Python. Because I have to calculate index'es based on start-addresses etc.
I have researched a bit and stumbled on functions like 'id()', and 'addressof()' but those weren't working.
Without using special implementations like PyPy or CPython, how would I achieve this? I knew that in Python you have very little options to do memory management, but it's said that everything done in C++ can be done in Python... So how would I create my own made array-list implementation in Python?
TL;DR
I have created my own 'array-implementation' in C++, but I want it in Python3. However Python has very little memory management options like 'new', pointers, references,... I'm still searching for a way to achieve this in Python.

Flatten a Two Dimensional array going in a clockwise direction [duplicate]

How do I print a 5×5 two-dimensional array in spiral order?
Is there any formula so that I can print an array of any size in spiral order?
The idea is to treat the matrix as a series of layers, top-right layers and bottom-left layers. To print the matrix spirally we can peel layers from these matrix, print the peeled part and recursively call the print on the left over part. The recursion terminates when we don't have any more layers to print.
Input matrix:
1 2 3 4
5 6 7 8
9 0 1 2
3 4 5 6
7 8 9 1
After peeling top-right layer:
1 2 3 4
8
5 6 7 2
9 0 1 6
3 4 5 1
7 8 9
After peeling bottom-left layer from sub-matrix:
6 7
5 0 1
9 4 5
3
7 8 9
After peeling top-right layer from sub-matrix:
6 7
1
0 5
4
After peeling bottom-left layer from sub-matrix:
0
4
Recursion terminates.
C functions:
// function to print the top-right peel of the matrix and
// recursively call the print bottom-left on the submatrix.
void printTopRight(int a[][COL], int x1, int y1, int x2, int y2) {
int i = 0, j = 0;
// print values in the row.
for(i = x1; i<=x2; i++) {
printf("%d ", a[y1][i]);
}
// print values in the column.
for(j = y1 + 1; j <= y2; j++) {
printf("%d ", a[j][x2]);
}
// see if more layers need to be printed.
if(x2-x1 > 0) {
// if yes recursively call the function to
// print the bottom left of the sub matrix.
printBottomLeft(a, x1, y1 + 1, x2-1, y2);
}
}
// function to print the bottom-left peel of the matrix and
// recursively call the print top-right on the submatrix.
void printBottomLeft(int a[][COL], int x1, int y1, int x2, int y2) {
int i = 0, j = 0;
// print the values in the row in reverse order.
for(i = x2; i>=x1; i--) {
printf("%d ", a[y2][i]);
}
// print the values in the col in reverse order.
for(j = y2 - 1; j >= y1; j--) {
printf("%d ", a[j][x1]);
}
// see if more layers need to be printed.
if(x2-x1 > 0) {
// if yes recursively call the function to
// print the top right of the sub matrix.
printTopRight(a, x1+1, y1, x2, y2-1);
}
}
void printSpiral(int arr[][COL]) {
printTopRight(arr,0,0,COL-1,ROW-1);
printf("\n");
}
Pop top row
Transpose and flip upside-down (same as rotate 90 degrees counter-clockwise)
Go to 1
Python 2 code:
import itertools
arr = [[1,2,3,4],
[12,13,14,5],
[11,16,15,6],
[10,9,8,7]]
def transpose_and_yield_top(arr):
while arr:
yield arr[0]
arr = list(reversed(zip(*arr[1:])))
print list(itertools.chain(*transpose_and_yield_top(arr)))
For python 3x:
import itertools
arr = [[1,2,3,4],
[12,13,14,5],
[11,16,15,6],
[10,9,8,7]]
def transpose_and_yield_top(arr):
while arr:
yield arr[0]
arr = list(reversed(list(zip(*arr[1:]))))
print(list(itertools.chain(*transpose_and_yield_top(arr))))
I see that no one has use only one for loop and without recursion in the code, and so I want to contribute.
The idea is like this:
Imagine there is a turtle standing at point (0,0), that is, top-left corner, facing east (to the right)
It will keep going forward and each time it sees a sign, the turtle will turn right
So if we put the turtle at point (0,0) facing right-ward, and if we place the signs at appropriate places, the turtle will traverse the array in spiral way.
Now the problem is: "Where to put the signs?"
Let's see where we should put the signs (marked by #, and numbers by O):
For a grid that looks like this:
O O O O
O O O O
O O O O
O O O O
We put the signs like this:
O O O #
# O # O
O # # O
# O O #
For a grid that looks like this:
O O O
O O O
O O O
O O O
We put the signs like this:
O O #
# # O
O # O
# O #
And for a grid that looks like this:
O O O O O O O
O O O O O O O
O O O O O O O
O O O O O O O
O O O O O O O
We put the signs like this:
O O O O O O #
# O O O O # O
O # O O # O O
O # O O O # O
# O O O O O #
We can see that, unless the point is at the top-left part, the signs are places at points where the distances to the closest horizontal border and the closest vertical border are the same, while for the top-left part, the distance to the top border is one more than the distance to the left border, with priority given to top-right in case the point is horizontally centered, and to top-left in case the point is vertically centered.
This can be realized in a simple function quite easily, by taking the minimum of (curRow and height-1-curRow), then the minimum of (curCol and width-1-curCol) and compare if they are the same. But we need to account for the upper-left case, that is, when the minimum is curRow and curCol themselves. In that case we reduce the vertical distance accordingly.
Here is the C code:
#include <stdio.h>
int shouldTurn(int row, int col, int height, int width){
int same = 1;
if(row > height-1-row) row = height-1-row, same = 0; // Give precedence to top-left over bottom-left
if(col >= width-1-col) col = width-1-col, same = 0; // Give precedence to top-right over top-left
row -= same; // When the row and col doesn't change, this will reduce row by 1
if(row==col) return 1;
return 0;
}
int directions[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
void printSpiral(int arr[4][4], int height, int width){
int directionIdx=0, i=0;
int curRow=0, curCol=0;
for(i=0; i<height*width; i++){
printf("%d ",arr[curRow][curCol]);
if(shouldTurn(curRow, curCol, height, width)){
directionIdx = (directionIdx+1)%4;
}
curRow += directions[directionIdx][0];
curCol += directions[directionIdx][1];
}
printf("\n");
}
int main(){
int arr[4][4]= {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
printSpiral(arr, 4, 4);
printSpiral(arr, 3, 4);
}
Which outputs:
1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10
1 2 3 4 8 12 11 10 9 5 6 7
Here are the three interesting ways
Reading in spiral way can be treated like a snake moving towards boundary and turning on hitting the boundary or itself (I find it elegant and most efficient being a single loop of N iterations)
ar = [
[ 0, 1, 2, 3, 4],
[15, 16, 17, 18, 5],
[14, 23, 24, 19, 6],
[13, 22, 21, 20, 7],
[12, 11, 10, 9, 8]]
def print_spiral(ar):
"""
assuming a rect array
"""
rows, cols = len(ar), len(ar[0])
r, c = 0, -1 # start here
nextturn = stepsx = cols # move so many steps
stepsy = rows-1
inc_c, inc_r = 1, 0 # at each step move this much
turns = 0 # how many times our snake had turned
for i in range(rows*cols):
c += inc_c
r += inc_r
print ar[r][c],
if i == nextturn-1:
turns += 1
# at each turn reduce how many steps we go next
if turns%2==0:
nextturn += stepsx
stepsy -= 1
else:
nextturn += stepsy
stepsx -= 1
# change directions
inc_c, inc_r = -inc_r, inc_c
print_spiral(ar)
output:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
A recursive approach would be to print outer layer and call same function for inner rectangle e.g.
def print_spiral(ar, sr=0, sc=0, er=None, ec=None):
er = er or len(ar)-1
ec = ec or len(ar[0])-1
if sr > er or sc > ec:
print
return
# print the outer layer
top, bottom, left, right = [], [], [], []
for c in range(sc,ec+1):
top.append(ar[sr][c])
if sr != er:
bottom.append(ar[er][ec-(c-sc)])
for r in range(sr+1,er):
right.append(ar[r][ec])
if ec != sc:
left.append(ar[er-(r-sr)][sc])
print " ".join([str(a) for a in top + right + bottom + left]),
# peel next layer of onion
print_spiral(ar, sr+1, sc+1, er-1, ec-1)
Finally here is a small snippet to do it, not efficient but fun :), basically it prints top row, and rotates whole rectangle anti-clockwise and repeats
def print_spiral(ar):
if not ar: return
print " ".join(str(a) for a in ar[0]),
ar = zip(*[ reversed(row) for row in ar[1:]])
print_spiral(ar)
This program works for any n*n matrix..
public class circ {
public void get_circ_arr (int n,int [][] a)
{
int z=n;
{
for (int i=0;i<n;i++)
{
for (int l=z-1-i;l>=i;l--)
{
int k=i;
System.out.printf("%d",a[k][l]);
}
for (int j=i+1;j<=z-1-i;j++)
{
int k=i;
{
System.out.printf("%d",a[j][k]);
}
}
for (int j=i+1;j<=z-i-1;j++)
{
int k=z-1-i;
{
System.out.printf("%d",a[k][j]);
}
}
for (int j=z-2-i;j>=i+1;j--)
{
int k=z-i-1;
{
System.out.printf("%d",a[j][k]);
}
}
}
}
}
}
Hope it helps
I was obsessed with this problem when I was learning Ruby. This was the best I could do:
def spiral(matrix)
matrix.empty? ? [] : matrix.shift + spiral(matrix.transpose.reverse)
end
You can check out some of my other solutions by stepping back through the revisions in this gist. Also, if you follow the link back to whom I forked the gist from, you'll find some other clever solutions. Really interesting problem that can be solved in multiple elegant ways — especially in Ruby.
JavaScript solution:
var printSpiral = function (matrix) {
var i;
var top = 0;
var left = 0;
var bottom = matrix.length;
var right = matrix[0].length;
while (top < bottom && left < right) {
//print top
for (i = left; i < right; i += 1) {
console.log(matrix[top][i]);
}
top++;
//print right column
for (i = top; i < bottom; i += 1) {
console.log(matrix[i][right - 1]);
}
right--;
if (top < bottom) {
//print bottom
for (i = right - 1; i >= left; i -= 1) {
console.log(matrix[bottom - 1][i]);
}
bottom--;
}
if (left < right) {
//print left column
for (i = bottom - 1; i >= top; i -= 1) {
console.log(matrix[i][left]);
}
left++;
}
}
};
One solution involves directions right, left, up, down, and their corresponding limits (indices). Once the first row is printed, and direction changes (from right) to down, the row is discarded by incrementing the upper limit. Once the last column is printed, and direction changes to left, the column is discarded by decrementing the right hand limit... Details can be seen in the self-explanatory C code.
#include <stdio.h>
#define N_ROWS 5
#define N_COLS 3
void print_spiral(int a[N_ROWS][N_COLS])
{
enum {up, down, left, right} direction = right;
int up_limit = 0,
down_limit = N_ROWS - 1,
left_limit = 0,
right_limit = N_COLS - 1,
downcount = N_ROWS * N_COLS,
row = 0,
col = 0;
while(printf("%d ", a[row][col]) && --downcount)
if(direction == right)
{
if(++col > right_limit)
{
--col;
direction = down;
++up_limit;
++row;
}
}
else if(direction == down)
{
if(++row > down_limit)
{
--row;
direction = left;
--right_limit;
--col;
}
}
else if(direction == left)
{
if(--col < left_limit)
{
++col;
direction = up;
--down_limit;
--row;
}
}
else /* direction == up */
if(--row < up_limit)
{
++row;
direction = right;
++left_limit;
++col;
}
}
void main()
{
int a[N_ROWS][N_COLS] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
print_spiral(a);
}
Link for Testing and Download.
Given a matrix of chars, implement a method that prints all characters in the following order: first the outer circle,
then the next one and so on.
public static void printMatrixInSpiral(int[][] mat){
if(mat.length == 0|| mat[0].length == 0){
/* empty matrix */
return;
}
StringBuffer str = new StringBuffer();
int counter = mat.length * mat[0].length;
int startRow = 0;
int endRow = mat.length-1;
int startCol = 0;
int endCol = mat[0].length-1;
boolean moveCol = true;
boolean leftToRight = true;
boolean upDown = true;
while(counter>0){
if(moveCol){
if(leftToRight){
/* printing entire row left to right */
for(int i = startCol; i <= endCol ; i++){
str.append(mat[startRow][i]);
counter--;
}
leftToRight = false;
moveCol = false;
startRow++;
}
else{
/* printing entire row right to left */
for(int i = endCol ; i >= startCol ; i--){
str.append(mat[endRow][i]);
counter--;
}
leftToRight = true;
moveCol = false;
endRow--;
}
}
else
{
if(upDown){
/* printing column up down */
for(int i = startRow ; i <= endRow ; i++){
str.append(mat[i][endCol]);
counter--;
}
upDown = false;
moveCol = true;
endCol--;
}
else
{
/* printing entire col down up */
for(int i = endRow ; i >= startRow ; i--){
str.append(mat[i][startCol]);
counter--;
}
upDown = true;
moveCol = true;
startCol++;
}
}
}
System.out.println(str.toString());
}
Two dimensional N*N Matrix is Square matrix
Idea:
We have to traverse in four different directions to traverse like spiral.
We have to traverse inside matrix once one layer of spiral is over.
So total, we need 5 loops, 4 loops to traverse like spiral and 1 loop to traverse through the layers.
public void printSpiralForm(int[][] a, int length)
{
for( int i = 0 , j = length-1 ; i < j ; i++ , j-- )
{
for( int k = i ; k < j ; k++ )
{
System.out.print( a[i][k] + " " ) ;
}
for( int k = i ; k < j ; k++ )
{
System.out.print(a[k][j] + " ");
}
for( int k = j ; k > i ; k-- )
{
System.out.print(a[j][k] + " ") ;
}
for( int k = j ; k > i ; k-- )
{
System.out.print( a[k][i] + " " ) ;
}
}
if ( length % 2 == 1 )
{
System.out.println( a[ length/2 ][ length/2 ] ) ;
}
}
Just keep it simple -->
public class spiralMatrix {
public static void printMatrix(int[][] matrix, int rows, int col)
{
int rowStart=0;
int rowEnd=rows-1;
int colStart=0;
int colEnd=col-1;
while(colStart<=colEnd && rowStart<=rowEnd)
{
for(int i=colStart;i<colEnd;i++)
System.out.println(matrix[rowStart][i]);
for(int i=rowStart;i<rowEnd;i++)
System.out.println(matrix[i][colEnd]);
for(int i=colEnd;i>colStart;i--)
System.out.println(matrix[rowEnd][i]);
for(int i=rowEnd;i>rowStart;i--)
System.out.println(matrix[i][colStart]);
rowStart++;
colEnd--;
rowEnd--;
colStart++;
}
}
public static void main(String[] args){
int[][] array={{1,2,3,4},{5,6,7,8}};
printMatrix(array,2,4);
}
}
This is my implementation:
public static void printMatrix(int matrix[][], int M, int N){
int level = 0;
int min = (M < N) ? M:N;
System.out.println();
while(level <= min/2){
for(int j = level; j < N - level - 1; j++){
System.out.print(matrix[level][j] + "\t");
}
for(int i = level; i < M - level - 1; i++) {
System.out.print(matrix[i][N - level - 1] + "\t");
}
for(int j = N - level - 1; j > level; j--){
System.out.print(matrix[M - level - 1][j] + "\t");
}
for(int i = M - level - 1; i > level; i-- ){
System.out.print(matrix[i][level] + "\t");
}
level++;
}
}
Here is my solution. Please correct if I'm wrong.
class Spiral:
def spiralOrder(self, A):
result = []
c = []
c.append(A[0])
b = A[1:]
while len(b) > 0:
b = self.rotate(b)
c.append(b[0])
b = b[1:]
for item in c:
for fitem in item:
print fitem,
result.append(fitem)
return result
def rotate(self,a):
b = []
l = zip(*a)
for i in xrange(len(l)-1,-1,-1):
b.append(list(l[i]))
return b
if __name__ == '__main__':
a = [[1, 2, 3,3], [4, 5, 6,6], [7, 8, 9,10]]
s = Spiral()
s.spiralOrder(a)
Slash Top Row -> Transpose -> Flip -> Repeat.
void slashTransposeFlip(int[][] m){
if( m.length * m[0].length == 1){ //only one element left
System.out.print(m[0][0]);
}else{
//print the top row
for(int a:m[0]){System.out.print(a+" ");}
//slash the top row from the matrix.
int[][] n = Arrays.copyOfRange(m,1,m.length);
int[][] temp = n;
int rows = temp.length;
int columns = temp[0].length;
//invert rows and columns and create new array
n = new int[columns][rows];
//transpose
for(int x=0;x<rows;x++)
for(int y=0;y<columns;y++)
n[y][x] = temp[x][y];
//flipping time
for (int i = 0; i < n.length / 2; i++) {
int[] t = n[i];
n[i] = n[n.length - 1 - i];
n[n.length - 1 - i] = t;
}
//recursively call again the reduced matrix.
slashTransposeFlip(n);
}
}
Complexity: Single traverse O(n)
Please let me add my single loop answer with complexity O(n). I have observed that during left-right and right-left traverse of the matrix, there is an increase and decrease by one respectively in the row-major index. Similarly, for the top-bottom and bottom-top traverse there is increase and decrease by n_cols. Thus I made an algorithm for that. For example, given a (3x5) matrix with entries the row-major indexes the print output is: 1,2,3,4,5,10,15,14,13,12,11,6,7,8,9.
------->(+1)
^ 1 2 3 4 5 |
(+n_cols) | 6 7 8 9 10 | (-n_cols)
| 11 12 13 14 15
(-1)<-------
Code solution:
#include <iostream>
using namespace std;
int main() {
// your code goes here
bool leftToRight=true, topToBottom=false, rightToLeft=false, bottomToTop=false;
int idx=0;
int n_rows = 3;
int n_cols = 5;
int cnt_h = n_cols, cnt_v = n_rows, cnt=0;
int iter=1;
for (int i=0; i <= n_rows*n_cols + (n_rows - 1)*(n_cols - 1)/2; i++){
iter++;
if(leftToRight){
if(cnt >= cnt_h){
cnt_h--; cnt=0;
leftToRight = false; topToBottom = true;
//cout << "Iter: "<< iter << " break_leftToRight"<<endl;
}else{
cnt++;
idx++;
//cout << "Iter: "<< iter <<" idx: " << idx << " cnt: "<< cnt << " cnt_h: "<< cnt_h<< endl;
cout<< idx << endl;
}
}else if(topToBottom){
if(cnt >= cnt_v-1){
cnt_v--; cnt=0;
leftToRight = false; topToBottom = false; rightToLeft=true;
//cout << "Iter: "<< iter << " break_topToBottom"<<endl;
}else{
cnt++;
idx+=n_cols;
//cout << "Iter: "<< iter << " idx: " << idx << " cnt: "<< cnt << " cnt_v: "<< cnt_h<< endl;
cout << idx <<endl;
}
}else if(rightToLeft){
if(cnt >= cnt_h){
cnt_h--; cnt=0;
leftToRight = false; topToBottom = false; rightToLeft=false; bottomToTop=true;
//cout << "Iter: "<< iter << " break_rightToLeft"<<endl;
//cout<< idx << endl;
}else{
cnt++;
idx--;
//cout << "Iter: "<< iter << " idx: " << idx << " cnt: "<< cnt << " cnt_h: "<< cnt_h<< endl;
cout << idx <<endl;
}
}else if(bottomToTop){
if(cnt >= cnt_v-1){
cnt_v--; cnt=0;
leftToRight = true; topToBottom = false; rightToLeft=false; bottomToTop=false;
//cout << "Iter: "<< iter << " break_bottomToTop"<<endl;
}else{
cnt++;
idx-=n_cols;
//cout << "Iter: "<< iter << " idx: " << idx << " cnt: "<< cnt << " cnt_v: "<< cnt_h<< endl;
cout<< idx << endl;
}
}
//cout << i << endl;
}
return 0;
}
function spiral(a) {
var s = [];
while (a.length) {
// concat 1st row, push last cols, rotate 180 (reverse inner/outer)...
s = s.concat(a.shift());
a = a
.map(function(v) {
s.push(v.pop());
return v.reverse();
})
.reverse();
}
return s;
}
var arr = [
[1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7]
];
console.log(spiral(arr));// -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
arr = [
[0, 1, 2, 3, 4],
[15, 16, 17, 18, 5],
[14, 23, 24, 19, 6],
[13, 22, 21, 20, 7],
[12, 11, 10, 9, 8]
];
console.log(spiral(arr));// -> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
For printing a 2-D matrix consider matrix as a composition of rectangles and/or line where smaller rectangle is fitted into larger one, take boundary of matrix which forms a rectangle to be printed, starting with up-left element each time in each layer; once done with this go inside for next layer of smaller rectangle, in case i don't have a rectangle then it should be line to be printed, a horizontal or vertical. I have pasted the code with an example matrix, HTH.
#include <stdio.h>
int a[2][4] = { 1, 2 ,3, 44,
8, 9 ,4, 55 };
void print(int, int, int, int);
int main() {
int row1, col1, row2, col2;
row1=0;
col1=0;
row2=1;
col2=3;
while(row2>=row1 && col2>=col1)
{
print(row1, col1, row2, col2);
row1++;
col1++;
row2--;
col2--;
}
return 0;
}
void print(int row1, int col1, int row2, int col2) {
int i=row1;
int j=col1;
/* This is when single horizontal line needs to be printed */
if( row1==row2 && col1!=col2) {
for(j=col1; j<=col2; j++)
printf("%d ", a[i][j]);
return;
}
/* This is when single vertical line needs to be printed */
if( col1==col2 && row1!=row2) {
for(i=row1; j<=row2; i++)
printf("%d ", a[i][j]);
return;
}
/* This is reached when there is a rectangle to be printed */
for(j=col1; j<=col2; j++)
printf("%d ", a[i][j]);
for(j=col2,i=row1+1; i<=row2; i++)
printf("%d ", a[i][j]);
for(i=row2,j=col2-1; j>=col1; j--)
printf("%d ", a[i][j]);
for(j=col1,i=row2-1; i>row1; i--)
printf("%d ", a[i][j]);
}
Here is my implementation in Java:
public class SpiralPrint {
static void spiral(int a[][],int x,int y){
//If the x and y co-ordinate collide, break off from the function
if(x==y)
return;
int i;
//Top-left to top-right
for(i=x;i<y;i++)
System.out.println(a[x][i]);
//Top-right to bottom-right
for(i=x+1;i<y;i++)
System.out.println(a[i][y-1]);
//Bottom-right to bottom-left
for(i=y-2;i>=x;i--)
System.out.println(a[y-1][i]);
//Bottom left to top-left
for(i=y-2;i>x;i--)
System.out.println(a[i][x]);
//Recursively call spiral
spiral(a,x+1,y-1);
}
public static void main(String[] args) {
int a[][]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
spiral(a,0,4);
/*Might be implemented without the 0 on an afterthought, all arrays will start at 0 anyways. The second parameter will be the dimension of the array*/
}
}
//shivi..coding is adictive!!
#include<shiviheaders.h>
#define R 3
#define C 6
using namespace std;
void PrintSpiral(int er,int ec,int arr[R][C])
{
int sr=0,sc=0,i=0;
while(sr<=er && sc<=ec)
{
for(int i=sc;i<=ec;++i)
cout<<arr[sr][i]<<" ";
++sr;
for(int i=sr;i<=er;++i)
cout<<arr[i][ec]<<" ";
ec--;
if(sr<=er)
{
for(int i=ec;i>=sc;--i)
cout<<arr[er][i]<<" ";
er--;
}
if(sc<=ec)
{
for(int i=er;i>=sr;--i)
cout<<arr[i][sc]<<" ";
++sc;
}
}
}
int main()
{
int a[R][C] = { {1, 2, 3, 4, 5, 6},
{7, 8, 9, 10, 11, 12},
{13, 14, 15, 16, 17, 18}
};
PrintSpiral(R-1, C-1, a);
}
int N = Integer.parseInt(args[0]);
// create N-by-N array of integers 1 through N
int[][] a = new int[N][N];
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
a[i][j] = 1 + N*i + j;
// spiral
for (int i = N-1, j = 0; i > 0; i--, j++) {
for (int k = j; k < i; k++) System.out.println(a[j][k]);
for (int k = j; k < i; k++) System.out.println(a[k][i]);
for (int k = i; k > j; k--) System.out.println(a[i][k]);
for (int k = i; k > j; k--) System.out.println(a[k][j]);
}
// special case for middle element if N is odd
if (N % 2 == 1) System.out.println(a[(N-1)/2][(N-1)/2]);
}
}
Java code if anybody is interested.
Input:
4
1 2 3 4
5 6 7 8
9 1 2 3
4 5 6 7
Output: 1 2 3 4 8 3 7 6 5 4 9 5 6 7 2 1
public class ArraySpiralPrinter {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); //marrix size
//read array
int[][] ar = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
ar[i][j] = sc.nextInt();
}
}
printTopRight(0, 0, n - 1, n - 1, ar);
}
//prints top and right layers.
//(x1,y1) to (x1, y2) - top layer & (x1,y2) to (x2, y2)
private static void printTopRight(int x1, int y1, int x2, int y2, int[][] ar) {
//print row values - top
for (int y = y1; y <= y2; y++) {
System.out.printf("%d ", ar[x1][y]);
}
//print column value - right
for (int x = x1 + 1; x <= x2; x++) {
System.out.printf("%d ", ar[x][y2]);
}
//are there any remaining layers
if (x2 - x1 > 0) {
//call printBottemLeft
printBottomLeft(x1 + 1, y1, x2, y2 - 1, ar);
}
}
//prints bottom and left layers in reverse order
//(x2,y2) to (x2, y1) - bottom layer & (x2,y1) to (x1, y1)
private static void printBottomLeft(int x1, int y1, int x2, int y2, int[][] ar) {
//print row values in reverse order - bottom
for (int y = y2; y >= y1; y--) {
System.out.printf("%d ", ar[x2][y]);
}
//print column value in reverse order - left
for (int x = x2-1; x >= x1; x--) {
System.out.printf("%d ", ar[x][y1]);
}
//are there any remaining layers
if (x2 - x1 > 0) {
printTopRight(x1, y1 + 1, x2 - 1, y2, ar);
}
}
}
This is a recursive version in C that I could think of:-
void printspiral (int[][100],int, int, int, int);
int main()
{
int r,c, i, j;
printf ("Enter the dimensions of the matrix");
scanf("%d %d", &r, &c);
int arr[r][100];
int min = (r<c?r:c);
if (min%2 != 0) min = min/2 +1;
for (i = 0;i<r; i++)
for (j = 0; j<c; j++)
scanf ("%d",&arr[i][j]);
printspiral(arr,0,r,c,min );
}
void printspiral (int arr[][100], int i, int j, int k, int min)
{
int a;
for (a = i; a<k;a++)
printf("%d\n", arr[i][a]);
for (a=i+1;a<j;a++)
printf ("%d\n", arr[a][k-1]);
for (a=k-2; a>i-1;a--)
printf("%d\n", arr[j-1][a]);
for (a=j-2; a>i; a--)
printf("%d\n", arr[a][i]);
if (i < min)
printspiral(arr,i+1, j-1,k-1, min);
}
http://www.technicalinterviewquestions.net/2009/03/print-2d-array-matrix-spiral-order.html
here is the best explanation for the above answer :) along with diagram :)
public static void printSpiral1(int array[][],int row,int col){
int rowStart=0,colStart=0,rowEnd=row-1,colEnd=col-1;
int i;
while(rowStart<=rowEnd && colStart<= colEnd){
for(i=colStart;i<=colEnd;i++)
System.out.print(" "+array[rowStart][i]);
for(i=rowStart+1;i<=rowEnd;i++)
System.out.print(" "+array[i][colEnd]);
for(i=colEnd-1;i>=colStart;i--)
System.out.print(" "+array[rowEnd][i]);
for(i=rowEnd-1;i>=rowStart+1;i--)
System.out.print(" "+array[i][colStart]);
rowStart++;
colStart++;
rowEnd--;
colEnd--;
}
}
public class SpiralPrint{
//print the elements of matrix in the spiral order.
//my idea is to use recursive, for each outer loop
public static void printSpiral(int[][] mat, int layer){
int up = layer;
int buttom = mat.length - layer - 1;
int left = layer;
int right = mat[0].length - layer - 1;
if(up > buttom+1 || left > right + 1)
return; // termination condition
//traverse the other frame,
//print up
for(int i = left; i <= right; i ++){
System.out.print( mat[up][i]+ " " );
}
//print right
for(int i = up + 1; i <=buttom; i ++){
System.out.print(mat[i][right] + " ");
}
//print buttom
for(int i = right - 1; i >= left; i --){
System.out.print(mat[buttom][i] + " ");
}
//print left
for(int i = buttom - 1; i > up; i --){
System.out.print(mat[i][left] + " ");
}
//recursive call for the next level
printSpiral(mat, layer + 1);
}
public static void main(String[] args){
int[][] mat = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16}};
int[][] mat2 = {{1,2,3}, {4,5,6}, {7,8,9}, {10,11,12}};
SpiralPrint.printSpiral(mat2,0);
return;
}
}
Here is my solution in C#:
public static void PrintSpiral(int[][] matrix, int n)
{
if (matrix == null)
{
return;
}
for (int layer = 0; layer < Math.Ceiling(n / 2.0); layer++)
{
var start = layer;
var end = n - layer - 1;
var offset = end - 1;
Console.Write("Layer " + layer + ": ");
// Center case
if (start == end)
{
Console.Write(matrix[start][start]);
}
// Top
for (int i = start; i <= offset; i++)
{
Console.Write(matrix[start][i] + " ");
}
// Right
for (int i = start; i <= offset; i++)
{
Console.Write(matrix[i][end] + " ");
}
// Bottom
for (int i = end; i > start; i--)
{
Console.Write(matrix[end][i] + " ");
}
// Left
for (int i = end; i > start; i--)
{
Console.Write(matrix[i][start] + " ");
}
Console.WriteLine();
}
}
Here's my approach using an Iterator . Note this solves almost the same problem..
Complete code here : https://github.com/rdsr/algorithms/blob/master/src/jvm/misc/FillMatrix.java
import java.util.Iterator;
class Pair {
final int i;
final int j;
Pair(int i, int j) {
this.i = i;
this.j = j;
}
#Override
public String toString() {
return "Pair [i=" + i + ", j=" + j + "]";
}
}
enum Direction {
N, E, S, W;
}
class SpiralIterator implements Iterator<Pair> {
private final int r, c;
int ri, ci;
int cnt;
Direction d; // current direction
int level; // spiral level;
public SpiralIterator(int r, int c) {
this.r = r;
this.c = c;
d = Direction.E;
level = 1;
}
#Override
public boolean hasNext() {
return cnt < r * c;
}
#Override
public Pair next() {
final Pair p = new Pair(ri, ci);
switch (d) {
case E:
if (ci == c - level) {
ri += 1;
d = changeDirection(d);
} else {
ci += 1;
}
break;
case S:
if (ri == r - level) {
ci -= 1;
d = changeDirection(d);
} else {
ri += 1;
}
break;
case W:
if (ci == level - 1) {
ri -= 1;
d = changeDirection(d);
} else {
ci -= 1;
}
break;
case N:
if (ri == level) {
ci += 1;
level += 1;
d = changeDirection(d);
} else {
ri -= 1;
}
break;
}
cnt += 1;
return p;
}
private static Direction changeDirection(Direction d) {
switch (d) {
case E:
return Direction.S;
case S:
return Direction.W;
case W:
return Direction.N;
case N:
return Direction.E;
default:
throw new IllegalStateException();
}
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
public class FillMatrix {
static int[][] fill(int r, int c) {
final int[][] m = new int[r][c];
int i = 1;
final Iterator<Pair> iter = new SpiralIterator(r, c);
while (iter.hasNext()) {
final Pair p = iter.next();
m[p.i][p.j] = i;
i += 1;
}
return m;
}
public static void main(String[] args) {
final int r = 19, c = 19;
final int[][] m = FillMatrix.fill(r, c);
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
System.out.print(m[i][j] + " ");
}
System.out.println();
}
}
}
Complete pure C program for any 2D array matrix with given row x column.
#include <stdio.h>
void printspiral(int *p,int r, int c) {
int i=0,j=0,m=1,n=0;
static int firstrun=1,gCol;
if (!p||r<=0||c<=0)
return ;
if(firstrun) {
gCol=c;
firstrun=0;
}
for(i=0,j=0;(0<=i && i<c)&&(0<=j && j<r);i+=m,j+=n) {
printf(" %d",p[i+j*gCol]);
if (i==0 && j==1 && (i+1)!=c) break;
else if (i+1==c && !j) {m=0;n=1;}
else if (i+1==c && j+1==r && j) {n=0;m=-1;}
else if (i==0 && j+1==r && j) {m=0;n=-1;}
}
printspiral(&p[i+j*gCol+1],r-2,c-2);
firstrun=1;
printf("\n");
}
int main() {
int a[3][3]={{0,1,2},{3,4,5},{6,7,8}};
int b[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};
int c[4][3]={{0,1,2},{3,4,5},{6,7,8},{9,10,11}};
int d[3][1]={{0},{1},{2}};
int e[1][3]={{0,1,2}};
int f[1][1]={{0}};
int g[5][5]={{0,1,2,3,4},{5,6,7,8,9},{10,11,12,13,14},{15,16,17,18,19},{20,21,22,23,24}};
printspiral(a,3,3);
printspiral(b,3,4);
printspiral(c,4,3);
printspiral(d,3,1);
printspiral(e,1,3);
printspiral(f,1,1);
printspiral(g,5,5);
return 0;
}
This question is related to this one: Matrix arrangement issues in php
The answers presented seem to work but are complicated to understand. A very simple way to solve this is divide and conquer i.e., after reading the edge, remove it and the next read will be much simpler. Check out a complete solution in PHP below:
#The source number matrix
$source[0] = array(1, 2, 3, 4);
$source[1] = array(5, 6, 7, 8);
$source[2] = array(9, 10, 11, 12);
$source[3] = array(13, 14, 15, 16);
$source[4] = array(17, 18, 19, 20);
#Get the spiralled numbers
$final_spiral_list = get_spiral_form($source);
print_r($final_spiral_list);
function get_spiral_form($matrix)
{
#Array to hold the final number list
$spiralList = array();
$result = $matrix;
while(count($result) > 0)
{
$resultsFromRead = get_next_number_circle($result, $spiralList);
$result = $resultsFromRead['new_source'];
$spiralList = $resultsFromRead['read_list'];
}
return $spiralList;
}
function get_next_number_circle($matrix, $read)
{
$unreadMatrix = $matrix;
$rowNumber = count($matrix);
$colNumber = count($matrix[0]);
#Check if the array has one row or column
if($rowNumber == 1) $read = array_merge($read, $matrix[0]);
if($colNumber == 1) for($i=0; $i<$rowNumber; $i++) array_push($read, $matrix[$i][0]);
#Check if array has 2 rows or columns
if($rowNumber == 2 || ($rowNumber == 2 && $colNumber == 2))
{
$read = array_merge($read, $matrix[0], array_reverse($matrix[1]));
}
if($colNumber == 2 && $rowNumber != 2)
{
#First read left to right for the first row
$read = array_merge($read, $matrix[0]);
#Then read down on right column
for($i=1; $i<$rowNumber; $i++) array_push($read, $matrix[$i][1]);
#..and up on left column
for($i=($rowNumber-1); $i>0; $i--) array_push($read, $matrix[$i][0]);
}
#If more than 2 rows or columns, pick up all the edge values by spiraling around the matrix
if($rowNumber > 2 && $colNumber > 2)
{
#Move left to right
for($i=0; $i<$colNumber; $i++) array_push($read, $matrix[0][$i]);
#Move top to bottom
for($i=1; $i<$rowNumber; $i++) array_push($read, $matrix[$i][$colNumber-1]);
#Move right to left
for($i=($colNumber-2); $i>-1; $i--) array_push($read, $matrix[$rowNumber-1][$i]);
#Move bottom to top
for($i=($rowNumber-2); $i>0; $i--) array_push($read, $matrix[$i][0]);
}
#Now remove these edge read values to create a new reduced matrix for the next read
$unreadMatrix = remove_top_row($unreadMatrix);
$unreadMatrix = remove_right_column($unreadMatrix);
$unreadMatrix = remove_bottom_row($unreadMatrix);
$unreadMatrix = remove_left_column($unreadMatrix);
return array('new_source'=>$unreadMatrix, 'read_list'=>$read);
}
function remove_top_row($matrix)
{
$removedRow = array_shift($matrix);
return $matrix;
}
function remove_right_column($matrix)
{
$neededCols = count($matrix[0]) - 1;
$finalMatrix = array();
for($i=0; $i<count($matrix); $i++) $finalMatrix[$i] = array_slice($matrix[$i], 0, $neededCols);
return $finalMatrix;
}
function remove_bottom_row($matrix)
{
unset($matrix[count($matrix)-1]);
return $matrix;
}
function remove_left_column($matrix)
{
$neededCols = count($matrix[0]) - 1;
$finalMatrix = array();
for($i=0; $i<count($matrix); $i++) $finalMatrix[$i] = array_slice($matrix[$i], 1, $neededCols);
return $finalMatrix;
}
// Program to print a matrix in spiral order
#include <stdio.h>
int main(void) {
// your code goes here
int m,n,i,j,k=1,c1,c2,r1,r2;;
scanf("%d %d",&m,&n);
int a[m][n];
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&a[i][j]);
}
}
r1=0;
r2=m-1;
c1=0;
c2=n-1;
while(k<=m*n)
{
for(i=c1;i<=c2;i++)
{
k++;
printf("%d ",a[r1][i]);
}
for(j=r1+1;j<=r2;j++)
{
k++;
printf("%d ",a[j][c2]);
}
for(i=c2-1;i>=c1;i--)
{
k++;
printf("%d ",a[r2][i]);
}
for(j=r2-1;j>=r1+1;j--)
{
k++;
printf("%d ",a[j][c1]);
}
c1++;
c2--;
r1++;
r2--;
}
return 0;
}

Interpret data from Modbus ASCII in C

I have a reply from a MODBUS ASCII protocol device.
I store the "data" part of the reply into an array in C:
char test_reply[10];
char buffer[255]; //contains all the reply from modbus device following ascii protocol
//store the "data part" of the reply to test_reply to fix endianness
test_reply[0] = buffer[9];
test_reply[1] = buffer[10];
test_reply[2] = buffer[7];
test_reply[3] = buffer[8];
test_reply[4] = buffer[13];
test_reply[5] = buffer[14];
test_reply[6] = buffer[11];
test_reply[7] = buffer[12];
I print this one and I got:
printf("this is the data reply: %s\n", test_reply)
"this is the data reply: 7B346543"
If I get the length of the string, I'm getting 8 (which I think is correct).
I believe each of those characters can be interpreted like this:
char(0x37) = 7
char(0x42) = B
char(0x33) = 3
and so on...
Now, I have to get a value of "229.20" from the reply.
What I do is manually input them to a variable and compute using a command in python.
like this:
>> x = chr(0x7B) + chr(0x34) + chr(0x65) +chr(0x43)
>> y = "".join(x)
>> z = struct.unpack("<f",y)
>> print z
(229.2050,)
I believe the way you do it in C is like on my previous post:
Unpacking in C
I want to ask if there is a way to do the other one in C
So what you need is a way to convert the 2 bytes sequence "7B" of { 0x37, 0x42 } to the single byte 0x7b.
sscanf with a x format is what you need. Assuming you know you have only 8 useful characters in test_reply, that you have already dealt with endianness on your platform and want to store them in a 32 bits float, you can do:
int i;
float z;
unsigned char *ix = (unsigned char *) &z; // you can always convert any address to a char *
for(i=0; i<4; i++) {
sscanf(test_reply + 2 * i, "%2hhx", &ix[i]); // 2 to process only 2 chars, hh to store only one byte
}
// control:
printf("%f\n", z); // should output 229.205002
You are receiving from ModBus ASCII value of the HEX representation of float 229,20. You must convert they manually like in the following example.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
uint8_t getDigit ( uint8_t digit)
{
uint8_t retVal = 0;
if ((digit >= '0') && (digit <= '9'))
{
retVal = digit - '0';
}
else if ((digit >= 'A') && (digit <= 'F'))
{
retVal = digit - 'A' + 10;
}
else if ((digit >= 'a') && (digit <= 'f'))
{
retVal = digit - 'a' + 10;
}
else
{
printf("Wrong char\n");
}
return retVal;
}
uint8_t ascii2bin (uint8_t hi, uint8_t lo)
{
uint8_t retVal = (getDigit(hi) << 4) | getDigit(lo);
return retVal;
}
int main()
{
char *ModBus_value = "33336543";
float yourFloatData;
char *special_ptr = (char *)(&yourFloatData);
int i;
int len = strlen(ModBus_value);
if ( len == (sizeof(float)*2) )
{
for (i=0; i<len; i+=2)
{
*special_ptr = ascii2bin(ModBus_value[i], ModBus_value[i+1]);
special_ptr++;
}
printf("yourFloatData_1: %f\n", yourFloatData );
}
else
{
printf("Wrong string\n");
}
return 0;
}
Other implementation, less readale of getDigit should be:
uint8_t getDigit ( uint8_t digit)
{
uint8_t retVal = 0;
if ((digit >= '0') && (digit <= '9'))
{
retVal = digit - '0';
}
else if ((digit >= 'A') && (digit <= 'F'))
{
retVal = digit - '7';
}
else if ((digit >= 'a') && (digit <= 'f'))
{
retVal = digit - 'W';
}
else
{
printf("Wrong char\n");
}
return retVal;
}
Or
uint8_t getDigit ( uint8_t digit)
{
uint8_t retVal = 0;
if ((digit >= '0') && (digit <= '9'))
{
retVal = digit - '0';
}
else if ((digit >= 'A') && (digit <= 'F'))
{
retVal = digit - 55;
}
else if ((digit >= 'a') && (digit <= 'f'))
{
retVal = digit - 87;
}
else
{
printf("Wrong char\n");
}
return retVal;
}
Or
uint8_t getDigit ( uint8_t digit)
{
uint8_t retVal = 0;
if ((digit >= '0') && (digit <= '9'))
{
retVal = digit - '0';
}
else if ((digit >= 'A') && (digit <= 'F'))
{
retVal = digit - 55;
}
else if ((digit >= 'a') && (digit <= 'f'))
{
retVal = digit - 87;
}
else
{
printf("Wrong char\n");
}
return retVal;
}

Making the diamond square fractal algorithm infinite

I'm trying to generate an infinite map, as such. I'm doing this in Python, and I can't get the noise libraries to correctly work (they don't seem to ever find my VS2010, and doing it in raw Python would be way too slow). As such, I'm trying to use the Diamond-Square Algorithm.
Would it be possible, in some way, to make this technically infinite?
If not, should I just go back to attempting to get one of the Python noise bindings to work?
This can be done. Divide up your landscape into "tiles", and apply the midpoint displacement algorithm (as I prefer to call it) within each tile.
Each tile must be big enough so that the height at one corner does not significantly depend on the height in another. In that way, you can create and destroy tiles on the fly, setting the height at newly appearing corners to an independent random value.
That value (and the randomness within the tile as well) must be seeded from the tile's position, so that you get the same tile each time.
The latest version of the noise module (at http://pypi.python.org/pypi/noise/1.0b3) mentions that it "fixed problems compiling with Visual C++ on Windows" - you might want to try it again. It installs and works properly for me (Python 2.7.1, MinGW, Windows 7).
If you arrange your tiles in an x,y grid and seed the random number generator for each tile like random.seed((x,y)), then every time you return to the same patch of world it will re-create the same terrain.
With the diamond-square algorithm, two sides of each tile depend on the adjoining tiles; however the dependence does not propagate all the way across the tile. If you let each tile depend on the tiles preceding it (ie above and to the left) and write a create_fake_tile function which assumes that all the preceding-tile values are 0, you get a "bad" tile in which the right column and bottom row are the correct values on which the next tile depends. If you draw each screen starting with the tile row and column preceding the first row and column on screen, then the visible portion of your world will be correct.
Can you apply midpoint displacement from the bottom up? Say you're working on a discrete grid, and you want to generate an MxN region. Get yourself a weighting function w(i). Start by applying a random displacement with weight w(0) to each point. Then apply a random displacement with weight w(1) to every other point, and propagate the displacement to intervening points. Then do every fourth point with w(2), again propagating. You can now generate a grid of any size, without having any starting assumption about the size.
If there's some N for which w(i > N) = 0, then you can stop generating when you hit it - which is rather important if you want the generation to ever terminate! You probably want a w function that starts at 1, increases to some value, and then falls off to zero; the increasing bit models the power-law roughness of terrain up to 100-km or so scales, and the decreasing bit models the fact that whole planets are more or less spherical. If you were doing Mars rather than Earth, you'd want w(i) to go further, because of the Tharsis bulge.
Now replace the random function with a random-looking but deterministic function of the point coordinates (feed the coordinates into a SHA1 hash, for example). Now, whenever you generate some particular part of the grid, it will look the same.
You should be able to do diamond-square in much the same way as this; you just need to alternate the shape of the displacements.
I solved the Diamond Squared algorithm for infinite landscapes.
function diamondSquaredMap(x, y, width, height, iterations) {
var map = fieldDiamondSquared(x, y, x+width, y+height, iterations);
var maxdeviation = getMaxDeviation(iterations);
for (var j = 0; j < width; j++) {
for (var k = 0; k < height; k++) {
map[j][k] = map[j][k] / maxdeviation;
map[j][k] = (map[j][k] + 1) / 2;
}
}
return map;
function create2DArray(d1, d2) {
var x = new Array(d1),
i = 0,
j = 0;
for (i = 0; i < d1; i += 1) {
x[i] = new Array(d2);
}
return x;
}
function fieldDiamondSquared(x0, y0, x1, y1, iterations) {
if (x1 < x0) { return null; }
if (y1 < y0) { return null; }
var finalwidth = x1 - x0;
var finalheight = y1 - y0;
var finalmap = create2DArray(finalwidth, finalheight);
if (iterations === 0) {
for (var j = 0; j < finalwidth; j++) {
for (var k = 0; k < finalheight; k++) {
finalmap[j][k] = displace(iterations,x0+j,y0+k) ;
}
}
return finalmap;
}
var ux0 = Math.floor(x0 / 2) - 1;
var uy0 = Math.floor(y0 / 2) - 1;
var ux1 = Math.ceil(x1 / 2) + 1;
var uy1 = Math.ceil(y1 / 2) + 1;
var uppermap = fieldDiamondSquared(ux0, uy0, ux1, uy1, iterations-1);
var uw = ux1 - ux0;
var uh = uy1 - uy0;
var cx0 = ux0 * 2;
var cy0 = uy0 * 2;
var cw = uw*2-1;
var ch = uh*2-1;
var currentmap = create2DArray(cw,ch);
for (var j = 0; j < uw; j++) {
for (var k = 0; k < uh; k++) {
currentmap[j*2][k*2] = uppermap[j][k];
}
}
var xoff = x0 - cx0;
var yoff = y0 - cy0;
for (var j = 1; j < cw-1; j += 2) {
for (var k = 1; k < ch-1; k += 2) {
currentmap[j][k] = ((currentmap[j - 1][k - 1] + currentmap[j - 1][k + 1] + currentmap[j + 1][k - 1] + currentmap[j + 1][k + 1]) / 4) + displace(iterations,cx0+j,cy0+k);
}
}
for (var j = 1; j < cw-1; j += 2) {
for (var k = 2; k < ch-1; k += 2) {
currentmap[j][k] = ((currentmap[j - 1][k] + currentmap[j + 1][k] + currentmap[j][k - 1] + currentmap[j][k + 1]) / 4) + displace(iterations,cx0+j,cy0+k);
}
}
for (var j = 2; j < cw-1; j += 2) {
for (var k = 1; k < ch-1; k += 2) {
currentmap[j][k] = ((currentmap[j - 1][k] + currentmap[j + 1][k] + currentmap[j][k - 1] + currentmap[j][k + 1]) / 4) + displace(iterations,cx0+j,cy0+k);
}
}
for (var j = 0; j < finalwidth; j++) {
for (var k = 0; k < finalheight; k++) {
finalmap[j][k] = currentmap[j+xoff][k+yoff];
}
}
return finalmap;
}
// Random function to offset
function displace(iterations, x, y) {
return (((PRH(iterations,x,y) - 0.5)*2)) / (iterations+1);
}
function getMaxDeviation(iterations) {
var dev = 0.5 / (iterations+1);
if (iterations <= 0) return dev;
return getMaxDeviation(iterations-1) + dev;
}
//This function returns the same result for given values but should be somewhat random.
function PRH(iterations,x,y) {
var hash;
x &= 0xFFF;
y &= 0xFFF;
iterations &= 0xFF;
hash = (iterations << 24);
hash |= (y << 12);
hash |= x;
var rem = hash & 3;
var h = hash;
switch (rem) {
case 3:
hash += h;
hash ^= hash << 32;
hash ^= h << 36;
hash += hash >> 22;
break;
case 2:
hash += h;
hash ^= hash << 22;
hash += hash >> 34;
break;
case 1:
hash += h;
hash ^= hash << 20;
hash += hash >> 2;
}
hash ^= hash << 6;
hash += hash >> 10;
hash ^= hash << 8;
hash += hash >> 34;
hash ^= hash << 50;
hash += hash >> 12;
return (hash & 0xFFFF) / 0xFFFF;
}
};
//CANVAS CONTROL
window.onload = terrainGeneration;
function terrainGeneration() {
"use strict";
var mapDimension,
roughness,
iterations,
mapCanvas = document.getElementById('canvas');
var update = document.getElementById('update');
var xpos = 0;
var ypos = 0;
mapDimension = 512;
mapCanvas.width = mapDimension;
mapCanvas.height = mapDimension;
var updatefunction = function() {
var elIterations = document.getElementById('iterations');
iterations = parseInt(elIterations.value, 10);
iterations = iterations || 6;
MoveMap(10,0);
}
update.onclick = updatefunction;
updatefunction();
function MoveMap(dx, dy) {
xpos -= dx;
ypos -= dy;
var map = diamondSquaredMap(xpos, ypos, mapDimension, mapDimension, iterations);
drawMap(mapDimension, "canvas", map);
}
var m = this;
m.map = document.getElementById("canvas");
m.width = mapDimension;
m.height = mapDimension;
m.hoverCursor = "auto";
m.dragCursor = "url(data:image/vnd.microsoft.icon;base64,AAACAAEAICACAAcABQAwAQAAFgAAACgAAAAgAAAAQAAAAAEAAQAAAAAAAAEAAAAAAAAAAAAAAgAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8AAAA/AAAAfwAAAP+AAAH/gAAB/8AAAH/AAAB/wAAA/0AAANsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////////////////////////////////////////////////////////////////////////////gH///4B///8Af//+AD///AA///wAH//+AB///wAf//4AH//+AD///yT/////////////////////////////8=), default";
m.scrollTime = 300;
m.mousePosition = new Coordinate;
m.mouseLocations = [];
m.velocity = new Coordinate;
m.mouseDown = false;
m.timerId = -1;
m.timerCount = 0;
m.viewingBox = document.createElement("div");
m.viewingBox.style.cursor = m.hoverCursor;
m.map.parentNode.replaceChild(m.viewingBox, m.map);
m.viewingBox.appendChild(m.map);
m.viewingBox.style.overflow = "hidden";
m.viewingBox.style.width = m.width + "px";
m.viewingBox.style.height = m.height + "px";
m.viewingBox.style.position = "relative";
m.map.style.position = "absolute";
function drawMap(size, canvasId, mapData) {
var canvas = document.getElementById(canvasId),
ctx = canvas.getContext("2d"),
x = 0,
y = 0,
colorFill,
img = ctx.createImageData(canvas.height, canvas.width);
for (x = 0; x < size; x++) {
for (y = 0; y < size; y++) {
colorFill = {r: 0, g: 0, b: 0};
var standardShade = Math.floor(mapData[x][y] * 250);
colorFill = {r: standardShade, g: standardShade, b: standardShade};
var pData = (x + (y * canvas.width)) * 4;
img.data[pData] = colorFill.r;
img.data[pData + 1] = colorFill.g;
img.data[pData + 2] = colorFill.b;
img.data[pData + 3] = 255;
}
}
ctx.putImageData(img, 0, 0);
}
function AddListener(element, event, f) {
if (element.attachEvent) {
element["e" + event + f] = f;
element[event + f] = function() {
element["e" + event + f](window.event)
};
element.attachEvent("on" + event, element[event + f])
} else
element.addEventListener(event, f, false)
}
function Coordinate(startX, startY) {
this.x = startX;
this.y = startY;
}
var MouseMove = function(b) {
var e = b.clientX - m.mousePosition.x;
var d = b.clientY - m.mousePosition.y;
MoveMap(e, d);
m.mousePosition.x = b.clientX;
m.mousePosition.y = b.clientY
};
/**
* mousedown event handler
*/
AddListener(m.viewingBox, "mousedown", function(e) {
m.viewingBox.style.cursor = m.dragCursor;
// Save the current mouse position so we can later find how far the
// mouse has moved in order to scroll that distance
m.mousePosition.x = e.clientX;
m.mousePosition.y = e.clientY;
// Start paying attention to when the mouse moves
AddListener(document, "mousemove", MouseMove);
m.mouseDown = true;
event.preventDefault ? event.preventDefault() : event.returnValue = false;
});
/**
* mouseup event handler
*/
AddListener(document, "mouseup", function() {
if (m.mouseDown) {
var handler = MouseMove;
if (document.detachEvent) {
document.detachEvent("onmousemove", document["mousemove" + handler]);
document["mousemove" + handler] = null;
} else {
document.removeEventListener("mousemove", handler, false);
}
m.mouseDown = false;
if (m.mouseLocations.length > 0) {
var clickCount = m.mouseLocations.length;
m.velocity.x = (m.mouseLocations[clickCount - 1].x - m.mouseLocations[0].x) / clickCount;
m.velocity.y = (m.mouseLocations[clickCount - 1].y - m.mouseLocations[0].y) / clickCount;
m.mouseLocations.length = 0;
}
}
m.viewingBox.style.cursor = m.hoverCursor;
});
}
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Canvas Terrain Generator</title>
<link rel="stylesheet" href="terrain.css" type="text/css">
<style type="text/css"></style><style type="text/css"></style></head>
<body>
Click and Pan.<br>
<div style="cursor: auto; overflow: hidden; width: 512px; height: 512px; position: relative;"><canvas id="canvas" width="512" height="512" style="position: absolute;"></canvas></div>
<br>
<form>
<fieldset>
<legend>Height Map Properties</legend>
<ol class="options">
<li>
<input type="text" name="iterations" id="iterations">
<label for="iterations">
Iterations(6)
</label>
</li>
</ol>
</fieldset>
<input type="button" value="Update" id="update">
</form>
</body></html>
https://jsfiddle.net/Tatarize/1Lrj3s2v/3/
Click and Drag jsfiddle
And actually found this question doing my due diligence. Yes. Though the answers provided here are mostly wrong it totally can be done. Conceptually what you need to do is view each iteration of the algorithm as an infinite field and the base case as an infinite field of perfectly random numbers. So each iteration is a diamond squared version of the previous one.
And to solve a range of say tile [100-200][100-200] at iteration 7, what you need is the entire block half that size (~a quarter that size h*w) at iteration 6 plus one extra edge on each side. So if you have a function that solves for a given tile:
getTerrain(x0,y0,x1,y1,iteration)... you can solve this for that tile if you have [49,101][49,101] at iteration 6. Then you simply apply diamond squared everywhere you can which won't work at the edges but will work everywhere else, and provide you with exactly enough data to solve for the tile [100-200][100-200] at iteration 7.
To get that tile at iteration 6 it will request [23-52][23-52] from iteration 5. And this will continue until iteration 0 just gives you [-1,3][-1,3] which will be 16 perfectly random values. If you requested a tile so large that iteration 0 didn't yet reach that size and position, you'll just need a different sliver which is fine because you're just making them up anyway.
In this way you get rid of the seeding step completely, simplify the algorithm, make it infinite, make it take a reasonable memory footprint. Using a deterministic pseudorandom number hashed from the coords and it will let you generate and regenerate the identical tiles on the fly, because you actually generated the upper lower iterations and just did so in a focused manner.
My blog has more information on it,
http://godsnotwheregodsnot.blogspot.com/2013/11/field-diamond-squared-fractal-terrain.html
In reality most of the complication of the algorithm comes from having the base case four points in a loop, as this is not close to the simplest case. And it's apparently escaped most people that you could have even simplified that by doing 1 point in a loop (though this is still pointlessly complex). Or anything that makes the algorithm seem to have at least 4x4 points. You could even start with 4x4 points iterate once, drop any row or column with an unknown value (all the edges), then have a 5x5 block, then a 7x7 block then an 11x11 block... (2n-3) x (2n-3).
In short, if you have an infinite field for your base case, you can actually have an infinite field, the iterations just determine how blended your stuff is. And if you use something deterministic for the pseudorandom injected offset, you pretty much have a very quick infinite landscape generator.
and here's a demonstration of it in javascript,
http://tatarize.nfshost.com/FieldDiamondSquare.htm
Here's an implementation in javascript. It simply gives you a view of the correct field at that iteration, position, and size. The above linked example uses this code in a movable canvas. It stores no data and recalculates each frame.
function diamondSquaredMap(x, y, width, height, iterations) {
var map = fieldDiamondSquared(x, y, x+width, y+height, iterations);
var maxdeviation = getMaxDeviation(iterations);
for (var j = 0; j < width; j++) {
for (var k = 0; k < height; k++) {
map[j][k] = map[j][k] / maxdeviation;
}
}
return map;
function create2DArray(d1, d2) {
var x = new Array(d1),
i = 0,
j = 0;
for (i = 0; i < d1; i += 1) {
x[i] = new Array(d2);
}
return x;
}
function fieldDiamondSquared(x0, y0, x1, y1, iterations) {
if (x1 < x0) { return null; }
if (y1 < y0) { return null; }
var finalwidth = x1 - x0;
var finalheight = y1 - y0;
var finalmap = create2DArray(finalwidth, finalheight);
if (iterations === 0) {
for (var j = 0; j < finalwidth; j++) {
for (var k = 0; k < finalheight; k++) {
finalmap[j][k] = displace(iterations,x0+j,y0+k) ;
}
}
return finalmap;
}
var ux0 = Math.floor(x0 / 2) - 1;
var uy0 = Math.floor(y0 / 2) - 1;
var ux1 = Math.ceil(x1 / 2) + 1;
var uy1 = Math.ceil(y1 / 2) + 1;
var uppermap = fieldDiamondSquared(ux0, uy0, ux1, uy1, iterations-1);
var uw = ux1 - ux0;
var uh = uy1 - uy0;
var cx0 = ux0 * 2;
var cy0 = uy0 * 2;
var cw = uw*2-1;
var ch = uh*2-1;
var currentmap = create2DArray(cw,ch);
for (var j = 0; j < uw; j++) {
for (var k = 0; k < uh; k++) {
currentmap[j*2][k*2] = uppermap[j][k];
}
}
var xoff = x0 - cx0;
var yoff = y0 - cy0;
for (var j = 1; j < cw-1; j += 2) {
for (var k = 1; k < ch-1; k += 2) {
currentmap[j][k] = ((currentmap[j - 1][k - 1] + currentmap[j - 1][k + 1] + currentmap[j + 1][k - 1] + currentmap[j + 1][k + 1]) / 4) + displace(iterations,cx0+j,cy0+k);
}
}
for (var j = 1; j < cw-1; j += 2) {
for (var k = 2; k < ch-1; k += 2) {
currentmap[j][k] = ((currentmap[j - 1][k] + currentmap[j + 1][k] + currentmap[j][k - 1] + currentmap[j][k + 1]) / 4) + displace(iterations,cx0+j,cy0+k);
}
}
for (var j = 2; j < cw-1; j += 2) {
for (var k = 1; k < ch-1; k += 2) {
currentmap[j][k] = ((currentmap[j - 1][k] + currentmap[j + 1][k] + currentmap[j][k - 1] + currentmap[j][k + 1]) / 4) + displace(iterations,cx0+j,cy0+k);
}
}
for (var j = 0; j < finalwidth; j++) {
for (var k = 0; k < finalheight; k++) {
finalmap[j][k] = currentmap[j+xoff][k+yoff];
}
}
return finalmap;
}
// Random function to offset
function displace(iterations, x, y) {
return (((PRH(iterations,x,y) - 0.5)*2)) / (iterations+1);
}
function getMaxDeviation(iterations) {
var dev = 0.5 / (iterations+1);
if (iterations <= 0) return dev;
return getMaxDeviation(iterations-1) + dev;
}
//This function returns the same result for given values but should be somewhat random.
function PRH(iterations,x,y) {
var hash;
x &= 0xFFF;
y &= 0xFFF;
iterations &= 0xFF;
hash = (iterations << 24);
hash |= (y << 12);
hash |= x;
var rem = hash & 3;
var h = hash;
switch (rem) {
case 3:
hash += h;
hash ^= hash << 32;
hash ^= h << 36;
hash += hash >> 22;
break;
case 2:
hash += h;
hash ^= hash << 22;
hash += hash >> 34;
break;
case 1:
hash += h;
hash ^= hash << 20;
hash += hash >> 2;
}
hash ^= hash << 6;
hash += hash >> 10;
hash ^= hash << 8;
hash += hash >> 34;
hash ^= hash << 50;
hash += hash >> 12;
return (hash & 0xFFFF) / 0xFFFF;
}
};
Updated to add, I went on from this, and made my own noise algorithm based on the same scoped field algorithm here, Here's the Jsfiddle for it.
https://jsfiddle.net/rkdzau7o/
You can click and drag the noise around.

Categories

Resources