Merge sort c++ not working [ambiguos error] - visual-c++

I have a merge sort and it will work when I do
mergeSort<int>(val_array1,numValues);
but once I change it to float
mergeSort<float>(val_array2,numValues);
I get this error:
1>c:\users\cbadau\documents\visual studio 2010\projects\lab\lab\lab12.cpp(71): error C2782: 'void recMergeSort(ItemType [],ItemType,ItemType)' : template parameter 'ItemType' is ambiguous
1> c:\users\cbadau\documents\visual studio 2010\projects\lab\lab\lab12.cpp(58) : see declaration of 'recMergeSort'
1> could be 'int'
1> or 'float'
1> c:\users\cbadau\documents\visual studio 2010\projects\lab\lab\lab12.cpp(96) : see reference to function template instantiation 'void mergeSort<float>(ItemType [],int)' being compiled
1> with
1> [
1> ItemType=float
1> ]
1>
Source Code:
#include<iostream>
using namespace std;
template<class ItemType>
void merge(ItemType list[], ItemType first, ItemType last, ItemType mid)
{
ItemType arraySize = last - first + 1;
ItemType* tempList = new ItemType[arraySize];
ItemType beginPart1 = first;
ItemType endPart1 = mid;
ItemType beginPart2 = mid + 1;
ItemType endPart2 = last;
int index = 0;
while (beginPart1 <= endPart1 && beginPart2 <= endPart2) {
if (list[beginPart1] < list[beginPart2]) {
tempList[index] = list[beginPart1];
beginPart1++;
}
else {
tempList[index] = list[beginPart2];
beginPart2++;
}
index++;
}
while (beginPart1 <= endPart1) {
tempList[index] = list[beginPart1];
index++;
beginPart1++;
}
while (beginPart2 <= endPart2) {
tempList[index] = list[beginPart2];
index++;
beginPart2++;
}
for (int i = first; i <= last; i++) {
list[i] = tempList[i - first];
}
delete[] tempList;
}
template<class ItemType>
void recMergeSort(ItemType list[], ItemType first, ItemType last)
{
if (first < last) {
ItemType mid = (first + last) / 2;
recMergeSort(list, first, mid);
recMergeSort(list, mid + 1, last);
merge(list, first, last, mid);
}
}
template<class ItemType>
void mergeSort(ItemType list[], int length)
{
recMergeSort(list, 0, length - 1);
}
int main()
{
int val_array1[] = {43, 7, 10, 23, 38, 4, 19, 51, 66, 14};
float val_array2[] = {43.2, 7.1, 10.5, 3.9, 18.7, 4.2, 19.3, 5.7, 66.8, 14.4};
int numValues = 10;
cout<<"val_array1 unsorted: "<<endl;
for(int i = 0; i <numValues; i++)
{
cout<<val_array1[i]<<endl;
}
cout<<"val_array2 unsorted: "<<endl;
for(int x=0; x <numValues; x++)
{
cout<<val_array2[x]<<endl;
}
mergeSort<int>(val_array1,numValues);
mergeSort<float>(val_array2,numValues);
cout<<"val_array1 sorted: "<<endl;
for(int y = 0; y <numValues; y++)
{
cout<<val_array1[y]<<endl;
}
cout<<"val_array2 sorted: "<<endl;
for(int t=0; t <numValues; t++)
{
cout<<val_array2[t]<<endl;
}
system("pause");
return 0;
}
Any ideas on what the problem is?

You have the same type for the values as for the indices in your template. Change ItemType to int for first, last, mid, etc.

Related

why am i getting expected primary-expression before '.' token [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 15 hours ago.
Improve this question
I am trying to create a Struct with two structs inside. One struct has a 2d array in it. The other struct packs 2 versions of the previous struct. I have a working code. However, in this code I have this statement:
`if (lane_bank_select == 0) {
for (uint8_t i = 0; i < lane_amount; i = i + 1) {
Serial.print(db.data_lane_bank_1[i].data_1);
Serial.print(" ");
Serial.print(db.data_lane_bank_1[i].data_2);
Serial.print(" ");
Serial.print(db.data_lane_bank_1[i].data_3);
Serial.print(" ");
Serial.println(db.data_lane_bank_1[i].data_4);
}
} else if (lane_bank_select == 1) {
for (uint8_t i = 0; i < lane_amount; i = i + 1) {
Serial.print(db.data_lane_bank_2[i].data_1);
Serial.print(" ");
Serial.print(db.data_lane_bank_2[i].data_2);
Serial.print(" ");
Serial.print(db.data_lane_bank_2[i].data_3);
Serial.print(" ");
Serial.println(db.data_lane_bank_2[i].data_4);
}
} else {
Serial.print(db.data_lane_bank_1[0].data_1);
Serial.print(" ");
Serial.print(db.data_lane_bank_1[0].data_2);
Serial.print(" ");
Serial.print(db.data_lane_bank_1[0].data_3);
Serial.print(" ");
Serial.println(db.data_lane_bank_1[0].data_4);
}`
I would like to change this statement to something like this.
`for (uint8_t i = 0; i < memory_amount; i = i + 1) {
if (lane_bank_select == i) {
for (uint8_t j = 0; j < bank_amount; j = j + 1) {
for (uint8_t k = 0; k < lane_amount; k = k + 1) {
for (uint8_t l = 0; l < data_amount; l = l + 1) {
Serial.print(db.data_lane_bank[j][k].data[l]);
Serial.println(" ");
}
}
}
}
}`
So i wrote this:
`const uint8_t memory_amount = 2;
const uint8_t bank_amount = 2;
const uint8_t data_amount = 4;
const uint8_t lane_amount = 4;
const uint8_t lane_array_size = 4;
uint8_t lane_bank_select = 0; // This is used to select the data lane bank
struct data_lane { // creates 4 variables for the data lane.
uint8_t data[data_amount];
};
// packs 2 versions of data_lane struct into one struct
struct data_bank {
data_lane data_lane_bank[bank_amount][lane_amount];
};
void setup() {
Serial.begin(9600);
}
void loop() {
// use serial port to select data_lane bank via lane_bank_select
serial_lane_select();
data_bank db = {
.data_lane_bank[0] = {
{ 1, 2, 3, 4 }, // Data_lane_1
{ 11, 12, 13, 14 }, // Data_lane_2
{ 21, 22, 23, 24 }, // Data_lane_3
{ 31, 32, 33, 34 }, // Data_lane_4
},
.data_lane_bank[1] = {
{ 41, 42, 43, 44 }, // Data_lane_1
{ 51, 52, 53, 54 }, // Data_lane_2
{ 61, 62, 63, 64 }, // Data_lane_3
{ 71, 72, 73, 74 }, // Data_lane_4
}
};
for (uint8_t i = 0; i < memory_amount; i = i + 1) {
if (lane_bank_select == i) {
for (uint8_t j = 0; j < bank_amount; j = j + 1) {
for (uint8_t k = 0; k < lane_amount; k = k + 1) {
for (uint8_t l = 0; l < data_amount; l = l + 1) {
Serial.print(db.data_lane_bank[j][k].data[l]);
Serial.println(" ");
}
}
}
}
}
}
void serial_lane_select() {
uint8_t lane_recieved;
if (Serial.available() > 0) {
lane_recieved = Serial.read();
if (lane_recieved == '1') // Single Quote! This is a character.
{
lane_bank_select = 0;
}
if (lane_recieved == '2') {
lane_bank_select = 1;
}
}
}`
I am now getting this error:
expected primary-expression before '.' token .data_lane_bank[0] =
Can somebody help please.

In place string manipulation for character count

Given a string, do in place replacement of every character with it's immediate count.
eg: "aaabbbcc" - "a3b3c2"
"abab" - "a1b1a1b1"
You can do something like below
function getResult(input) {
if(!input) {
return ''; // if string is empty, return ''
}
if (input.length === 1) { // if string length is 1, return input + '1'
return input + '1'
}
var inputLength = input.length; // total length of the input string
var preChar = input[0]; // track previous character
var count = 1; // count of the previous character
for (var i = 1; i < inputLength; i++) {
if (preChar === input[i]) { // previous char and current char match
preChar = input[i]; // update prevChar with current char
count++; // count of prevChar is incremented
if (i + 1 < inputLength) { // not the end of the string
input = input.substr(0, i) + '#' + input.substr(i + 1); // update with dummy char '#' to maintain the length of the string, later will be removed
} else { // if it is the end of the string, update with count
input = input.substr(0, i) + count + input.substr(i + 1);
}
continue;
}
// if current char is not matched with prevChar
preChar = input[i]; // update the preChar with current char
// update the input with prevChar count and current char
input = input.substr(0, i) + count + input[i] + input.substr(i + 1);
inputLength++; // new count is added in the string, so total length of the string is increased by one
i++; // increment the i also because total length is increased
count = 1; // update the count with 1
if (i + 1 === inputLength) { // if it is last element
input = input.substr(0, i+1) + count + input.substr(i + 2);
}
}
input = input.replace(/\#/g, '') // remove dummy char '#' with ''
return input; // return the input
}
console.log("result for aaabbbcc is ", getResult('aaabbbcc'))
console.log("result for abab is ", getResult('abab'))
This answer assumes the OP uses ASCII
Analysis of the requirement of the the OP
Analysis of the bytes required:
When there is 1 repeat only, 2 bytes are needed.
When there are 2 repeats, 2 bytes are needed.
When there are 3, 2 bytes are needed.
When there are 9, 2 bytes.
When there are 99, 3 bytes.
When there are 999, 4 bytes.
When there are (2^64 - 1) repeats, only 20 bytes are needed.
As you can see, the bytes required to express the integer are log10(N)(at least 1) where N is the number of repeats.
Repeat-once
So, when there is only 1 repeat and there is no spare space, it has to keep iterating until
sequence that have more bytes than needed(have at least 3 repeats) to give it space
to reallocate when the end is reached
(In a string where most repeat at least twice or thrice and those who only repeat once are not gathered in one place, this is seldom required. This algorithm makes this assumption).
Then, the string will be modified backward to prevent any overwritten of data. This work because for each repeat-once sequence, it will take up double bytes to store them, so when the sequence at i will be written at 2i.
C++14 Code
#include <algorithm>
#include <cassert>
#include <utility>
#include <type_traits>
// Definition of helper functions for converting ints to string(raw and no need for format string).
template <class size_t, class UnsignedInt,
class = std::enable_if_t<std::is_unsigned<UnsignedInt>::value>>
size_t to_str_len(UnsignedInt i) noexcept
{
size_t cnt = 0;
do {
++cnt;
i /= 10;
} while (i > 0);
return cnt;
}
/*
* out should either points to the beginning of array or the last.
* step should be either 1 or -1.
*/
template <class RandomAccessIt, class UnsignedInt,
class = std::enable_if_t<std::is_unsigned<UnsignedInt>::value>>
auto uitos_impl(RandomAccessIt out, int step, UnsignedInt i) noexcept
{
do {
*out = static_cast<char>(i % 10) + 48;
out += step;
i /= 10;
} while (i > 0);
return out;
}
template <class BidirectionalIt>
void reverse_str(BidirectionalIt beg, BidirectionalIt end) noexcept
{
do {
std::iter_swap(beg++, --end);
} while (beg < end);
}
template <class RandomAccessIt, class UnsignedInt>
auto uitos(RandomAccessIt beg, UnsignedInt i) noexcept
{
auto ret = uitos_impl(beg, 1, i);
// Reverse the string to get the right order
reverse_str(beg, ret);
return ret;
}
template <class RanIt, class UnsignedInt>
auto r_uitos(RanIt last, UnsignedInt i) noexcept
{
return uitos_impl(last, -1, i);
}
template <class size_t, class RandomAccessIt>
size_t count_repeat(RandomAccessIt beg, RandomAccessIt end) noexcept
{
auto first = beg;
auto &val = *beg;
do {
++beg;
} while (beg != end && *beg == val);
return beg - first;
}
template <class size_t, class RandomAccessIt>
size_t r_count_repeat(RandomAccessIt last) noexcept
{
auto it = last;
auto &val = *it;
do {
--it;
} while (*it == val);
return last - it;
}
template <class string,
class size_type = typename string::size_type>
struct character_count
{
static_assert(std::is_unsigned<size_type>::value,
"size_type should be unsigned");
static_assert(!std::is_empty<size_type>::value,
"size_type should not be empty");
private:
using str_size_t = typename string::size_type;
using str_it = typename string::iterator;
static_assert(std::is_same<typename string::value_type, char>::value,
"Only support ASCII");
static_assert(sizeof(size_type) <= sizeof(str_size_t),
"size_type should not be bigger than typename string::size_type");
string str;
str_it in;
str_it out;
str_it end;
size_type len;
void cnt_repeat() noexcept
{
assert(in != end);
len = count_repeat<size_type>(in, str.end());
}
void advance_in() noexcept
{
assert(in != end);
in += len;
assert(in <= end);
}
void process_impl()
{
assert(in != end);
assert(out <= in);
// The main loop
do {
cnt_repeat();
if (len > 1 || out < in) {
*out = *in;
out = uitos(out + 1, len);
advance_in();
assert(out <= in);
} else {
auto first = find_enough_space();
auto deduced_first = write_backward();
assert(first == deduced_first);
}
} while (in != end);
}
auto find_enough_space()
{
assert(out == in);
auto first = in;
size_type bytes_required = 0;
do {
cnt_repeat();
advance_in();
bytes_required += to_str_len<size_type>(len) + 1;
if (size_type(in - first) >= bytes_required) {
out = first + bytes_required;
return first;
}
} while (in != str.end());
auto first_offset = first - str.begin();
// Hopefully this path won't be executed.
auto new_size = first_offset + bytes_required;
auto original_size = str.size();
assert(new_size > original_size);
str.resize(new_size);
first = str.begin() + first_offset;
out = str.end();
in = str.begin() + original_size;
end = str.begin() + original_size;
return first;
}
auto write_backward() noexcept
{
auto original_out = out--;
auto original_in = in--;
do {
len = r_count_repeat<size_type>(in);
out = r_uitos(out, len);
*out-- = *((in -= len) + 1);
} while (out != in);
auto ret = out + 1;
out = original_out;
in = original_in;
return ret;
}
public:
character_count(string &&arg):
str(std::move(arg)), in(str.begin()), out(str.begin()), end(str.end())
{}
character_count(const string &arg):
str(arg), in(str.begin()), out(str.begin()), end(str.end())
{}
/*
* ```str``` should not be empty and should not have non-visible character
*/
auto& process()
{
assert(!str.empty());
process_impl();
str.erase(out, str.end());
return *this;
}
auto& get_result() & noexcept
{
return str;
}
auto&& get_result() && noexcept
{
return std::move(str);
}
auto& get_result() const& noexcept
{
return str;
}
/*
* ```str``` should not be empty and should not have non-visible character
*/
auto& set_string(const string &arg) noexcept
{
str = arg;
in = str.begin();
out = str.begin();
end = str.end();
return *this;
}
/*
* ```str``` should not be empty and should not have non-visible character
*/
auto& set_string(string &&arg) noexcept
{
str = std::move(arg);
in = str.begin();
out = str.begin();
end = str.end();
return *this;
}
};
Assuming you're using Javascript, this is how I would do it. Just match all the groups with a regex and loop over them:
function charCount (str) {
const exp = /(\w)\1*/g
let matches = (str).match(exp)
let output = ''
matches.forEach(group => {
output += group[0] + group.length
})
return output
}
const str = 'abab'
const str2 = 'aaabbbcc'
console.log(charCount(str)) // a1b1a1b1
console.log(charCount(str2)) // a3b3c2

Find rank of lottery combinations

I need to find the rank/index of a lottery combination and be able to reverse the process (Find the lottery combination given its rank).
Consider a lottery game with 5 balls from 1 to 45 and 1 powerball from 1 to 20. Duplication is not allowed and the order does not matter. The number of combinations is:
(45 * 44 * 43 * 42 * 41 / 5!) * 20 = 24,435,180
The first combination (index 0) is:
1, 2, 3, 4, 5, 1
The last combination (index 24,435,179) is:
41, 42, 43, 44, 45, 20
How can I convert a combination into its index and vice versa without exhaustively enumerating all combinations?
I came across this MSDN article, which shows how to get the combination of a given index. However, I don't know how to get the index from a combination. I've tried:
Choose(c1,k) + Choose(c2,k-1) + Choose(c3,k-2) + Choose(c4,k-3) ...
Where ci is the number at position i in the ordered combination set and k is the size of the set. Since the index of a combination depends on the range of the elements, this does not work. Additionally, I'm not sure if it is going to work with elements of different sizes in the set (e.g. main pool's range is 1-45, powerball's range is 1-20)
I was able to figure it out. I created a new Combination class, based on the MSDN example, which can convert a combination to an index and vice versa. A separate index is retrieved for each pool of numbers. All the indices are then combined to represent a combination with elements of different sizes.
A Pool class was also created to represent the settings of a pool (Range of elements, size etc). The Pool class:
public class Pool {
public int From { get; set; }
public int To { get; set; }
public int Size { get; set; }
public int Numbers { get { return (To - From + 1); } }
public Pool(int From, int To, int Size) {
this.From = From;
this.To = To;
this.Size = Size ;
}
}
The Combination class:
class Combination {
public Pool[] Pools { get; set; }
public long[][] Data { get; set; } //First index represents pool index, second represents the numbers
public Combination(Pool[] Pools, long[][] Data) {
this.Pools = Pools;
this.Data = Data;
if (Data.GetLength(0) != Pools.Length) {
throw (new ArgumentException("Invalid data length"));
}
for (int i = 0; i < Data.GetLength(0); i++) {
if (Data[i].Length != Pools[i].Size) {
throw (new ArgumentException("Invalid data length"));
}
}
}
public static Combination FromIndex(long Index, Pool[] Pools) {
long[][] elements = new long[Pools.Length][];
long[] c = new long[Pools.Length - 1];
long cumulative = 1;
for (int i = 0; i < Pools.Length - 1; i++) {
c[i] = Combination.Choose(Pools[i].Numbers, Pools[i].Size);
checked {
cumulative *= c[i];
}
}
for (int i = Pools.Length - 1; i >= 1; i--) {
long ind = Index / cumulative;
Index -= ind * cumulative;
cumulative /= c[i - 1];
elements[i] = Combination.FromIndex(ind, Pools[i]);
}
elements[0] = Combination.FromIndex(Index, Pools[0]);
return (new Combination(Pools, elements));
}
public static long[] FromIndex(long Index, Pool Pool) {
long[] ans = new long[Pool.Size];
long a = (long)Pool.Numbers;
long b = (long)Pool.Size;
long x = GetDual((long)Pool.Numbers, (long)Pool.Size, Index);
for (int k = 0; k < Pool.Size; k++) {
ans[k] = LargestV(a, b, x);
x -= Choose(ans[k], b);
a = ans[k];
b--;
}
for (int k = 0; k < Pool.Size; k++) {
ans[k] = ((long)Pool.Numbers - 1) - ans[k];
}
//Transform to relative
for (int i = 0; i < ans.Length; i++) {
ans[i] += Pool.From;
}
return (ans);
}
private static long GetDual(long To, long Size, long m) {
return (Choose(To, Size) - 1) - m;
}
public static long Choose(long To, long Size) {
if (To < 0 || Size < 0)
throw new Exception("Invalid negative parameter in Choose()");
if (To < Size)
return 0; // special case
if (To == Size)
return 1;
long delta, iMax;
if (Size < To - Size) {
delta = To - Size;
iMax = Size;
} else {
delta = Size;
iMax = To - Size;
}
long ans = delta + 1;
for (long i = 2; i <= iMax; ++i) {
checked {
ans = (ans * (delta + i)) / i;
}
}
return ans;
}
private static long LargestV(long a, long b, long x) {
long v = a - 1;
while (Choose(v, b) > x)
--v;
return v;
}
public long ToIndex() {
long Index = 0;
long cumulative = 1;
for (int i = 0; i < Pools.Length; i++) {
checked {
Index += ToIndex(i) * cumulative;
cumulative *= Combination.Choose(Pools[i].Numbers, Pools[i].Size);
}
}
return (Index);
}
public long ToIndex(int PoolIndex) {
long ind = 0;
for (int i = 0; i < Pools[PoolIndex].Size; i++) {
long d = (Pools[PoolIndex].Numbers - 1) - (Data[PoolIndex][i] - Pools[PoolIndex].From);
ind += Choose(d, Pools[PoolIndex].Size - i);
}
ind = GetDual(Pools[PoolIndex].Numbers, Pools[PoolIndex].Size, ind);
return (ind);
}
public override string ToString() {
string s = "{ ";
for (int i = 0; i < Data.Length; ++i) {
for (int k = 0; k < Data[i].Length; k++) {
s += Data[i][k] + " ";
}
if (i != Data.Length - 1) {
s += "| ";
}
}
s += "}";
return s;
}
}
To see this in action:
//Create pools
Pool[] pools = new Pool[2];
pools[0] = new Pool(1, 45, 5);
pools[1] = new Pool(1, 20, 1);
//Create a combination
long[][] data = new long[][] { new long[] { 41, 42, 43, 44, 45 }, new long[] { 20 } };
Combination combination = new Combination(pools, data);
//Get index from combination:
long index = combination.ToIndex();
Console.WriteLine("Index: " + index);
//Get combination from index:
Combination combFromIndex = Combination.FromIndex(index, pools);
Console.WriteLine("Combination: " + combFromIndex);
Output:
Index: 24435179
Combination: { 41 42 43 44 45 | 20 }

Jaro–Winkler distance algorithm in C#

How would the Jaro–Winkler distance string comparison algorithm be implemented in C#?
public static class JaroWinklerDistance
{
/* The Winkler modification will not be applied unless the
* percent match was at or above the mWeightThreshold percent
* without the modification.
* Winkler's paper used a default value of 0.7
*/
private static readonly double mWeightThreshold = 0.7;
/* Size of the prefix to be concidered by the Winkler modification.
* Winkler's paper used a default value of 4
*/
private static readonly int mNumChars = 4;
/// <summary>
/// Returns the Jaro-Winkler distance between the specified
/// strings. The distance is symmetric and will fall in the
/// range 0 (perfect match) to 1 (no match).
/// </summary>
/// <param name="aString1">First String</param>
/// <param name="aString2">Second String</param>
/// <returns></returns>
public static double distance(string aString1, string aString2) {
return 1.0 - proximity(aString1,aString2);
}
/// <summary>
/// Returns the Jaro-Winkler distance between the specified
/// strings. The distance is symmetric and will fall in the
/// range 0 (no match) to 1 (perfect match).
/// </summary>
/// <param name="aString1">First String</param>
/// <param name="aString2">Second String</param>
/// <returns></returns>
public static double proximity(string aString1, string aString2)
{
int lLen1 = aString1.Length;
int lLen2 = aString2.Length;
if (lLen1 == 0)
return lLen2 == 0 ? 1.0 : 0.0;
int lSearchRange = Math.Max(0,Math.Max(lLen1,lLen2)/2 - 1);
// default initialized to false
bool[] lMatched1 = new bool[lLen1];
bool[] lMatched2 = new bool[lLen2];
int lNumCommon = 0;
for (int i = 0; i < lLen1; ++i) {
int lStart = Math.Max(0,i-lSearchRange);
int lEnd = Math.Min(i+lSearchRange+1,lLen2);
for (int j = lStart; j < lEnd; ++j) {
if (lMatched2[j]) continue;
if (aString1[i] != aString2[j])
continue;
lMatched1[i] = true;
lMatched2[j] = true;
++lNumCommon;
break;
}
}
if (lNumCommon == 0) return 0.0;
int lNumHalfTransposed = 0;
int k = 0;
for (int i = 0; i < lLen1; ++i) {
if (!lMatched1[i]) continue;
while (!lMatched2[k]) ++k;
if (aString1[i] != aString2[k])
++lNumHalfTransposed;
++k;
}
// System.Diagnostics.Debug.WriteLine("numHalfTransposed=" + numHalfTransposed);
int lNumTransposed = lNumHalfTransposed/2;
// System.Diagnostics.Debug.WriteLine("numCommon=" + numCommon + " numTransposed=" + numTransposed);
double lNumCommonD = lNumCommon;
double lWeight = (lNumCommonD/lLen1
+ lNumCommonD/lLen2
+ (lNumCommon - lNumTransposed)/lNumCommonD)/3.0;
if (lWeight <= mWeightThreshold) return lWeight;
int lMax = Math.Min(mNumChars,Math.Min(aString1.Length,aString2.Length));
int lPos = 0;
while (lPos < lMax && aString1[lPos] == aString2[lPos])
++lPos;
if (lPos == 0) return lWeight;
return lWeight + 0.1 * lPos * (1.0 - lWeight);
}
}
You can take a look on Lucene.Net ,
it implement Jaro–Winkler distance algorithm ,
and its score is different from which leebickmtu post ,
you can take it as reference
the url is below :
http://lucenenet.apache.org/docs/3.0.3/db/d12/_jaro_winkler_distance_8cs_source.html
You can use the below code which works very well for all the kind of strings.After getting the result you need to multiply with 100 to get the percentage of similarity. I hope it will solves your problem.
public class JaroWinkler
{
private const double defaultMismatchScore = 0.0;
private const double defaultMatchScore = 1.0;
/// <summary>
/// Gets the similarity between two strings by using the Jaro-Winkler algorithm.
/// A value of 1 means perfect match. A value of zero represents an absolute no match
/// </summary>
/// <param name="_firstWord"></param>
/// <param name="_secondWord"></param>
/// <returns>a value between 0-1 of the similarity</returns>
///
public static double RateSimilarity(string _firstWord, string _secondWord)
{
// Converting to lower case is not part of the original Jaro-Winkler implementation
// But we don't really care about case sensitivity in DIAMOND and wouldn't decrease security names similarity rate just because
// of Case sensitivity
_firstWord = _firstWord.ToLower();
_secondWord = _secondWord.ToLower();
if ((_firstWord != null) && (_secondWord != null))
{
if (_firstWord == _secondWord)
//return (SqlDouble)defaultMatchScore;
return defaultMatchScore;
else
{
// Get half the length of the string rounded up - (this is the distance used for acceptable transpositions)
int halfLength = Math.Min(_firstWord.Length, _secondWord.Length) / 2 + 1;
// Get common characters
StringBuilder common1 = GetCommonCharacters(_firstWord, _secondWord, halfLength);
int commonMatches = common1.Length;
// Check for zero in common
if (commonMatches == 0)
//return (SqlDouble)defaultMismatchScore;
return defaultMismatchScore;
StringBuilder common2 = GetCommonCharacters(_secondWord, _firstWord, halfLength);
// Check for same length common strings returning 0 if is not the same
if (commonMatches != common2.Length)
//return (SqlDouble)defaultMismatchScore;
return defaultMismatchScore;
// Get the number of transpositions
int transpositions = 0;
for (int i = 0; i < commonMatches; i++)
{
if (common1[i] != common2[i])
transpositions++;
}
int j = 0;
j += 1;
// Calculate Jaro metric
transpositions /= 2;
double jaroMetric = commonMatches / (3.0 * _firstWord.Length) + commonMatches / (3.0 * _secondWord.Length) + (commonMatches - transpositions) / (3.0 * commonMatches);
//return (SqlDouble)jaroMetric;
return jaroMetric;
}
}
//return (SqlDouble)defaultMismatchScore;
return defaultMismatchScore;
}
/// <summary>
/// Returns a string buffer of characters from string1 within string2 if they are of a given
/// distance seperation from the position in string1.
/// </summary>
/// <param name="firstWord">string one</param>
/// <param name="secondWord">string two</param>
/// <param name="separationDistance">separation distance</param>
/// <returns>A string buffer of characters from string1 within string2 if they are of a given
/// distance seperation from the position in string1</returns>
private static StringBuilder GetCommonCharacters(string firstWord, string secondWord, int separationDistance)
{
if ((firstWord != null) && (secondWord != null))
{
StringBuilder returnCommons = new StringBuilder(20);
StringBuilder copy = new StringBuilder(secondWord);
int firstWordLength = firstWord.Length;
int secondWordLength = secondWord.Length;
for (int i = 0; i < firstWordLength; i++)
{
char character = firstWord[i];
bool found = false;
for (int j = Math.Max(0, i - separationDistance); !found && j < Math.Min(i + separationDistance, secondWordLength); j++)
{
if (copy[j] == character)
{
found = true;
returnCommons.Append(character);
copy[j] = '#';
}
}
}
return returnCommons;
}
return null;
}
}
Use below class to use jaro winkler.
i have customized both algorithm jaro and jaro-winkler.
Visit on Github for DLL.
using System;
using System.Linq;
namespace Search
{
public static class EditDistance
{
private struct JaroMetrics
{
public int Matches;
public int Transpositions;
}
private static EditDistance.JaroMetrics Matches(string s1, string s2)
{
string text;
string text2;
if (s1.Length > s2.Length)
{
text = s1;
text2 = s2;
}
else
{
text = s2;
text2 = s1;
}
int num = Math.Max(text.Length / 2 - 1, 0);
int[] array = new int[text2.Length];
int i;
for (i = 0; i < array.Length; i++)
{
array[i] = -1;
}
bool[] array2 = new bool[text.Length];
int num2 = 0;
for (int j = 0; j < text2.Length; j++)
{
char c = text2[j];
int k = Math.Max(j - num, 0);
int num3 = Math.Min(j + num + 1, text.Length);
while (k < num3)
{
if (!array2[k] && c == text[k])
{
array[j] = k;
array2[k] = true;
num2++;
break;
}
k++;
}
}
char[] array3 = new char[num2];
char[] ms2 = new char[num2];
i = 0;
int num4 = 0;
while (i < text2.Length)
{
if (array[i] != -1)
{
array3[num4] = text2[i];
num4++;
}
i++;
}
i = 0;
num4 = 0;
while (i < text.Length)
{
if (array2[i])
{
ms2[num4] = text[i];
num4++;
}
i++;
}
int num5 = array3.Where((char t, int mi) => t != ms2[mi]).Count<char>();
EditDistance.JaroMetrics result;
result.Matches = num2;
result.Transpositions = num5 / 2;
return result;
}
public static float JaroWinkler(this string s1, string s2, float prefixScale, float boostThreshold)
{
prefixScale = ((prefixScale > 0.25f) ? 0.25f : prefixScale);
prefixScale = ((prefixScale < 0f) ? 0f : prefixScale);
float num = s1.Jaro(s2);
int num2 = 0;
for (int i = 0; i < Math.Min(s1.Length, s2.Length); i++)
{
if (s1[i] != s2[i])
{
break;
}
num2++;
}
return (num < boostThreshold) ? num : (num + prefixScale * (float)num2 * (1f - num));
}
public static float JaroWinkler(this string s1, string s2, float prefixScale)
{
return s1.JaroWinkler(s2, prefixScale, 0.7f);
}
public static float JaroWinkler(this string s1, string s2)
{
return s1.JaroWinkler(s2, 0.1f, 0.7f);
}
public static float Jaro(this string s1, string s2)
{
EditDistance.JaroMetrics jaroMetrics = EditDistance.Matches(s1, s2);
float num = (float)jaroMetrics.Matches;
int transpositions = jaroMetrics.Transpositions;
float result;
if (num == 0f)
{
result = 0f;
}
else
{
float num2 = (num / (float)s1.Length + num / (float)s2.Length + (num - (float)transpositions) / num) / 3f;
result = num2;
}
return result;
}
public static int LevenshteinDistance(this string source, string target)
{
int result;
if (string.IsNullOrEmpty(source))
{
if (string.IsNullOrEmpty(target))
{
result = 0;
}
else
{
result = target.Length;
}
}
else if (string.IsNullOrEmpty(target))
{
result = source.Length;
}
else
{
if (source.Length > target.Length)
{
string text = target;
target = source;
source = text;
}
int length = target.Length;
int length2 = source.Length;
int[,] array = new int[2, length + 1];
for (int i = 1; i <= length; i++)
{
array[0, i] = i;
}
int num = 0;
for (int j = 1; j <= length2; j++)
{
num = (j & 1);
array[num, 0] = j;
int num2 = num ^ 1;
for (int i = 1; i <= length; i++)
{
int num3 = (target[i - 1] == source[j - 1]) ? 0 : 1;
array[num, i] = Math.Min(Math.Min(array[num2, i] + 1, array[num, i - 1] + 1), array[num2, i - 1] + num3);
}
}
result = array[num, length];
}
return result;
}
}
}

Fractal generation from infinite sum

I found a project description on a course website for computer graphics. I am trying to complete the project for fun.
Here is the link to the problem description:
http://www.pdfhost.net/index.php?Action=Download&File=901bc7785bef41364b3a40f6f4493926
Below is my code. The problem I am running in to is that the terms of the series grow so fast I can't map the points to the screen correctly. From the problem description it says the points will be mappable within a -2 - 2 square but the difference in value between the points is so huge that normalizing by the largest would collapse most of the points to a single pixel.
I assume I have a fundamental misunderstanding that I can't identify. Any help or insight would be appreciated!
int w = 800, h = 600;
int numTimes = 10, cSize = 5;
float xr = 2, yr = 2;
void setup() {
size(w,h);
}
void draw() {
background(255);
Complex v = new Complex(mouseX*(xr/w) - (xr/2), mouseY*(yr/h) - (yr/2));
Complex[] exps = new Complex[numTimes];
for (int i = 0; i < numTimes; i++) {
exps[i] = complexExp(v,i);
}
ellipse(w/2, h/2, cSize, cSize);
for (int i = 0; i < numTimes; i++) {
drawSeries(new Complex(0,0), exps, i, i);
}
}
void drawSeries(Complex vToDraw, Complex[] exps, int count, int clrTrunc) {
if (count == 0) {
Complex v = exps[0];
float progress = float(clrTrunc) / float(numTimes);
fill(255*progress, 180, 255 - 255*progress);
vToDraw.add(v);
ellipse(vToDraw.r*(w/xr) + (w/2), vToDraw.i*(h/xr) + h/2, cSize, cSize);
vToDraw.sub(v);
vToDraw.sub(v);
ellipse(vToDraw.r*(w/xr) + (w/2), vToDraw.i*(h/xr) + h/2, cSize, cSize);
} else {
Complex v = exps[count];
vToDraw.add(v);
drawSeries(vToDraw, exps, count - 1, clrTrunc );
vToDraw.sub(v);
vToDraw.sub(v);
drawSeries(vToDraw, exps, count - 1,clrTrunc );
}
}
Complex complexExp(Complex v, int times) {
if (times == 0) {
return new Complex(1, 1);
} else if ( times == 1) {
return new Complex( v.r*v.r - v.i*v.i, 2*v.r*v.i );
} else {
return complexExp( new Complex( v.r*v.r - v.i*v.i, 2*v.r*v.i ), times - 1 );
}
}
class Complex {
float r, i;
Complex() {
this.r = 0;
this.i = 0;
}
Complex(float r, float i) {
this.r = r;
this.i = i;
}
void add(Complex nv) {
this.r += nv.r;
this.i += nv.i;
}
void sub(Complex nv) {
this.r -= nv.r;
this.i -= nv.i;
}
}
I think you can make the code cleaner if you write a more complete Complex class.
int w = 800, h = 600;
int numTimes = 10, cSize = 5;
float xr = 3, yr = 3;
void setup() {
size(w,h);
noLoop();
}
void mousePressed() {
redraw();
}
void draw() {
background(255);
Complex v = new Complex(mouseX*(xr/w) - (xr/2), mouseY*(yr/h) - (yr/2));
Complex[] exps = new Complex[numTimes];
for (int i = 0; i < numTimes; i++) {
exps[i] = v.raisedTo(i);
print(exps[i]);
}
ellipse(w/2, h/2, cSize, cSize);
print(exps);
drawSerie(exps, numTimes);
}
void drawSerie(Complex[] exps, int total)
{
Complex partial = new Complex(0, 0);
drawPartial(exps, total -1, partial);
}
void drawFinal(Complex toDraw)
{
point(toDraw.r*(w/xr) + (w/2), toDraw.i*(h/xr) + h/2);
}
void drawPartial(Complex [] exps, int depth, Complex partial)
{
if (depth == -1)
{
drawFinal(partial);
return;
}
int nextDepth = depth -1;
drawPartial(exps, nextDepth, partial);
Complex element = exps[depth];
drawPartial(exps, nextDepth, partial.add(element));
drawPartial(exps, nextDepth, partial.sub(element));
}
class Complex {
float r, i;
Complex() {
this.r = 0;
this.i = 0;
}
Complex(float r, float i) {
this.r = r;
this.i = i;
}
Complex(Complex other)
{
this.r = other.r;
this.i = other.i;
}
Complex mult(Complex other)
{
return new Complex(this.r*other.r - this.i*other.i, this.r*other.i + this.i*other.r);
}
Complex add(Complex nv) {
return new Complex(this.r + nv.r, this.i + nv.i);
}
Complex sub(Complex nv) {
return new Complex(this.r - nv.r, this.i - nv.i);
}
Complex raisedTo(int n) {
if (n == 0) {
return new Complex(1, 0);
}
else if (n % 2 == 0)
{
return (this.mult(this)).raisedTo(n/2);
}
else
{
return this.mult(this.raisedTo(n - 1 ));
}
}
String toString()
{
return "real: " + this.r + " imaginary: " + this.i;
}
}
The computation of the series is not efficient but, I think, it is clear

Resources