Converting a roman numeral to integer - matlab

For a computer science assignment my goal is to convert a character string (the roman numeral) to an integer. I'm to write a function to do this in Matlab. My code to do this is shown below.
function [x] = roman2decimal(s)
s1 = substr1(s,1);
s2 = substr2(s,2,2);
s = substr2(s, 3, numel(s));
sum = 0;
if (s1~='')
%Case I - if any of these conditions are true
if (s1=='C' && s2=='M')
sum = sum + 900;
end
if (s1=='C' && s2=='D')
sum = sum + 400;
end
if (s1=='X' && s2=='C')
sum = sum + 90;
end
if (s1=='X' && s2=='L')
sum = sum + 40;
end
if (s1=='I' && s2=='X')
sum = sum + 9;
end
if (s1=='I' && s2=='V')
sum = sum + 4;
end
s=s1
s2=substr2(s, 3, numel(s))
end
% case 2 - no case 1 conditions were true
if(s1=='M')
sum = sum + 1000;
end
if(s1=='D')
sum = sum + 500;
end
if(s1=='C')
sum = sum + 100;
end
if(s1=='L')
sum = sum + 50;
end
if(s1=='X')
sum = sum + 10;
end
if(s1=='V')
sum = sum + 5;
end
if(s1=='I')
sum = sum + 1;
end
s1=s2
s=s2
sum
end
function [c]=substr1(s,pos)
if(pos >= 1 && numel(s) >= pos) c=s(pos);
else c='';
end
end % substr1
function [c]=substr2(s,pos1,pos2)
if(pos1 >=1 && pos2 >= pos1 && pos2 <= numel(s)) c=s(pos1:pos2);
else c='';
end
end % substr2
The issue I'm having is that when I call the function for a character string that's more than 2 characters long, s1 always computes to the second character in the string, e.g. for 'CM' s1=M, s2=M.
If I call the substr1 function outside of this function, it works fine (e.g. returns the first character in the string).
I was wondering if there was something wrong with my algorithm/syntax and if you could help?
Much appreciated.

Here is an answer inspired by #Robert, yet quite different:
myStr = 'MCMLXXXVIII';
key = 'MDCLXVI';
values = [1000, 500,100,50,10,5,1];
% Calculate the 'weight' of each letter
[~, loc]=ismember(myStr,key)
relevantValues = values(loc);
% Determine whether we should substract or add
s = [-sign(diff(relevantValues)), 1];
%% To avoid zeros in s
while ~all(s)
f = find(s == 0);
s(f) = s(f+1);
end
s*relevantValues'
This vectorized approach minimizes the amount of string operations and avoids eval statements.

This solution is in C and has passed all the 3999 test cases in LeetCode
int romanToInt(char* s) {
int i = 0, value = 0;
for (int i =0; s[i] != '\0'; i++)
{
switch(s[i]) {
case 'I':
if(s[i+1] != '\0' ){
if(s[i+1] == 'V' ||s[i+1] == 'X' )
value = value -1;
else
value = value+1;
}else {
value = value+1;
}
break;
case 'V':
value = value + 5;
break;
case 'X':
if(s[i+1] != '\0' ){
if(s[i+1] == 'L' ||s[i+1] == 'C' )
value = value -10;
else
value = value+10;
}else {
value = value+10;
}
break;
case 'L':
value = value + 50;
break;
case 'C':
if(s[i+1] != '\0' ){
if(s[i+1] == 'D' ||s[i+1] == 'M' )
value = value -100;
else
value = value+100;
}else {
value = value+100;
}
break;
case 'D':
value = value + 500;
break;
case 'M':
value = value + 1000;
break;
}
}
return value;
}

Related

coffeescript prime number generation

I am trying to generate prime numbers like this:
generatePrimeNumbersBelowN = (n) ->
for i in [2..n-1]
isPrime = true
for j in [2..i-1]
isPrime = false if i % j == 0
break if not isPrime
console.log(i, "is Prime Number.") if isPrime
generatePrimeNumbersBelowN(100);
I am getting prime numbers from 3 to 97, inclusive. I am new to JavaScript/CoffeeScript, so please tell me what's happening to 2?
Here's the generated JS code:
var generatePrimeNumbersBelowN;
generatePrimeNumbersBelowN = function(n) {
var i, isPrime, j, k, l, ref, ref1, results;
results = [];
for (i = k = 2, ref = n - 1; 2 <= ref ? k <= ref : k >= ref; i = 2 <= ref ? ++k : --k) {
isPrime = true;
for (j = l = 2, ref1 = i - 1; 2 <= ref1 ? l <= ref1 : l >= ref1; j = 2 <= ref1 ? ++l : --l) {
if (i % j === 0) {
isPrime = false;
}
if (!isPrime) {
break;
}
}
if (isPrime) {
results.push(console.log(i, "is Prime Number."));
} else {
results.push(void 0);
}
}
return results;
};
generatePrimeNumbersBelowN(100);
generatePrimeNumbersBelowN = (n) ->
for i in [2..n-1]
isPrime = true
for j in [2..i-1]
isPrime = false if i % j == 0
break if not isPrime
console.log(i, "is Prime Number.") if isPrime
When i is 2, j ranges from 2 down to 1. You then check i % j which is 2 % 1 which is zero and claim that 2 is not a prime.
Because for x in [b..a] delivers a downward loop from b to a, while loop construct solves this problem.
generatePrimeNumbersBelowN = (n) ->
i = 2
while i < n
isPrime = true
j = 2
while j < i
isPrime = false if i % j == 0
break if not isPrime
j++
console.log(i, "is Prime Number.") if isPrime
i++
generatePrimeNumbersBelowN(100);

Filter points using hist in matlab

I have a vector. I want to remove outliers. I got bin and no of values in that bin. I want to remove all points based on the number of elements in each bin.
Data:
d1 =[
360.471912914169
505.084636471948
514.39429429184
505.285068055647
536.321181755858
503.025854206322
534.304229816684
393.387035881967
396.497969729985
520.592172434431
421.284713703215
420.401106087984
537.05330275495
396.715779872694
514.39429429184
404.442344469518
476.846474245118
599.020867750031
429.163139144079
514.941744277933
445.426761656729
531.013596812737
374.977332648255
364.660115724218
538.306752697753
519.042387479096
1412.54699036882
405.571202133485
516.606049132218
2289.49623498271
378.228766753667
504.730621222846
358.715764917016
462.339366699398
512.429858614816
394.778786157514
366
498.760463549388
366.552861126468
355.37022947906
358.308526273099
376.745272034036
366.934599077274
536.0901883079
483.01740134285
508.975480745389
365.629593988233
536.368800360349
557.024236456548
366.776498701866
501.007025898839
330.686029339009
508.395475983019
429.563732174866
2224.68806802212
534.655786464525
518.711297351426
534.304229816684
514.941744277933
420.32368479542
367.129404978681
525.626188464768
388.329756778952
1251.30895065927
525.626188464768
412.313764019587
513.697381733643
506.675438520558
1517.71183364959
550.276294237722
543.359917550053
500.639590923451
395.129864728041];
Histogram computation:
[nelements,centers] = hist(d1);
nelements=55 13 0 0 1 1 1 0 0 2
I want to remove all points apearing less than 5 (in nelements). It means only first 2 elements in nelements( 55, 13 ) remains.
Is there any function in matlab.
You can do it along these lines:
threshold = 5;
bin_halfwidth = (centers(2)-centers(1))/2;
keep = ~any(abs(bsxfun(#minus, d1, centers(nelements<threshold))) < bin_halfwidth , 2);
d1_keep = d1(keep);
Does this do what you want?
binwidth = centers(2)-centers(1);
centersOfRemainingBins = centers(nelements>5);
remainingvals = false(length(d1),1);
for ii = 1:length(centersOfRemainingBins )
remainingvals = remainingvals | (d1>centersOfRemainingBins (ii)-binwidth/2 & d1<centersOfRemainingBins (ii)+binwidth/2);
end
d_out = d1(remainingvals);
I don't know Matlab function for this problem, but I think, that function with follow code is what are you looking for:
sizeData = size(data);
function filter_hist = filter_hist(data, binCountRemove)
if or(max(sizeData) == 0, binCountRemove < 1)
disp('Error input!');
filter_hist = [];
return;
end
[n, c] = hist(data);
sizeN = size(n);
intervalSize = c(2) - c(1);
if sizeData(1) > sizeData(2)
temp = transpose(data);
else
temp = data;
end
for i = 1:1:max(sizeN)
if n(i) < binCountRemove
a = c(i) - intervalSize / 2;
b = c(i) + intervalSize / 2;
sizeTemp = size(temp);
removeInds = [];
k = 0;
for j = 1:1:max(sizeTemp)
if and(temp(j) > a, less_equal(temp(j), b) == 1)
k = k + 1;
removeInds(k) = j;
end
end
temp(removeInds) = [];
end
end
filter_hist = transpose(temp);
%Determines when 'a' less or equal to 'b' by accuracy
function less_equal = less_equal(a, b)
delta = 10^-6; %Accuracy
if a < b
less_equal = 1;
return;
end
if abs(b - a) < delta
less_equal = 1;
return;
end
less_equal = 0;
You can do something like this
nelements=nelements((nelements >5))

returning the index in an insertion sorting

I want to know how to return the indices of the original elements in the insertion sort algorithm such as the function [B,IX] = sort(A,...) in matlab.
The algorithm is:
function list = insertionSort(list)
for i = (2:numel(list))
value = list(i);
j = i - 1;
while (j >= 1) && (list(j) > value)
list(j+1) = list(j);
j = j-1;
end
list(j+1) = value;
end %for
end %insertionSort
I want a function [list indx]= insSort(list) to return the sorted elements with its original indices.
Hope this isn't homework.
function [ind, list] = insertionSort(list)
ind = [1:length(list)]'; % build list of indicies
for i = (2:numel(list))
value = list(i);
j = i - 1;
while (j >= 1) && (list(j) > value)
list(j+1) = list(j);
ind(j+1) = ind(j); % copy index when you shift
j = j-1;
end
list(j+1) = value;
ind(j+1) = i; % write final index location
end
end

Matlab error : Subscript indices must either be real positive integers or logicals

I have the following error in MATLAB:
??? Subscript indices must either be real positive integers or
logicals.
Error in ==> Lloyd_Max at 74 D(w_count) = mean((x -
centers(xq)).^2);
This is my code :
function [ xq,centers,D ] = Lloyd_Max( x,N,min_value,max_value )
%LLOYD_MAX Summary of this function goes here
% Detailed explanation goes here
x = x';
temp = (max_value - min_value)/2^N;
count=1;
for j=0:temp:((max_value - min_value)-temp),
centers(count) = (j + j + temp )/2;
count = count + 1;
end
for i=1:length(centers),
k(i) = centers(i);
end
w_count = 0;
while((w_count < 2) || (D(w_count) - D(w_count - 1) > 1e-6))
w_count = w_count + 1;
count1 = 2;
for i=2:(count-1),
T(i) = (k(i-1) + k(i))/2;
count1 = count1 +1 ;
end
T(1) = min_value;
T(count1) = max_value;
index = 1;
for j=2:count1,
tempc = 0;
tempk = 0;
for k=1:10000,
if(x(k) >= T(j-1) && x(k) < T(j))
tempk = tempk + x(k);
tempc = tempc + 1;
end
end
k(index) = tempk;
k_count(index) = tempc;
index = index + 1;
end
for i=1:length(k),
k(i) = k(i)/k_count(i);
end
for i=1:10000,
if (x(i) > max_value)
xq(i) = max_value;
elseif (x(i) < min_value)
xq(i) = min_value;
else
xq(i) = x(i);
end
end
for i=1:10000,
cnt = 1;
for l=2:count1,
if(xq(i) > T(l-1) && xq(i) <= T(l))
xq(i) = cnt;
end
cnt = cnt +1 ;
end
end
D(w_count) = mean((x - centers(xq)).^2);
end
end
and i call it and have these inputs :
M = 10000
t=(randn(M,1)+sqrt(-1)*randn(M,1))./sqrt(2);
A= abs(t).^2;
[xq,centers,D] = Lloyd_Max( A,2,0,4 );
I tried to comment the while and the D, Results :
I got the xq and the centers all normal, xq in the 1-4 range, centers 1-4 indexes and 0.5-3.5 range.
I dont know whats going wrong here...Please help me.
Thank in advance!
MYSTERY SOVLED!
Thank you all guys for your help!
I just putted out of the while the for loop :
for i=1:10000,
if (x(i) > max_value)
xq(i) = max_value;
elseif (x(i) < min_value)
xq(i) = min_value;
else
xq(i) = x(i);
end
end
and it worked like charm.... this loop was initilizing the array again. Sorry for that. Thank you again!
There is an assignment xq(i) = x(i) somewhere in the middle of your function, but you pass A as x from outside where you calculate A from t which is sampled by randn, so you can't promise xq is an integer.
I'm not sure exactly what you are aiming to do, but your vector xq does not contain integers, it contains doubles. If you want to use a vector of indices as you do with centers(xq), all elements of the vector need to be integers.
Upon a little inspection, it looks like xq are x values, you should find some way to map them to the integer of the closest cell to which they belong (i'm guessing 'centers' represents centers of cells?)

How to implement priority queue in matlab

Is there any library in matlab that provides the functionality of min priorityqueue
import java.util.PriorityQueue;
import java.util.*;
public class MyQueue {
Comparator<Double> c;
PriorityQueue<Double> PQ;
public MyQueue() {
c = new Comparator<Double>(){
public int compare(Double o1, Double o2){
if(o2 > o1) {
return -1;
} else if(o1 > o2) {
return 1;
} else {
return 0;
}
}
};
PQ = new PriorityQueue<Double>(1000,c);
}
public void addElement(double d) {
PQ.add(d);
}
public double removeElement() {
return(PQ.remove());
}
}
I have implemented this priorty queue in java. I can call it from matlab. However, I need to associate each cost with an index. I mean it's not only cost of the node that i need to store but also its index. How can I accomplish this. I need to pass the index from matlab
You can use Java's default PriorityQueue like so:
>> q=java.util.PriorityQueue;
>> q.add({value,index});
This is available since Java ≥ 1.5, which is pre-bundled in all MATLAB releases since 7.0.4 (R14).
Otherwise, you can use the one from the file exchange, which you'll have to compile.
There's also a Simulink block for it, but I doubt that's what you're after.
Below is a resizing-array implementation of a priority queue written entirely in matlab. You can attach/couple any kind of data/index you want along with the priority value. Also, you can switch/toggle the behaviour between a min and max priority queue through a boolean argument passed into the constructor when it is created.
classdef PriorityQueue < handle
properties (SetAccess = private)
numElements;
priorityList;
valueList;
flagMaxPriorityQueue;
end
methods (Access = public)
function obj = PriorityQueue( flagMaxPriorityQueue )
if ~exist( 'flagMaxPriorityQueue', 'var' )
flagMaxPriorityQueue = true;
else
if ~(isscalar(flagMaxPriorityQueue) && islogical(flagMaxPriorityQueue))
error( 'ERROR: invalid flagMaxPriorityQueue argument' );
end
end
obj.flagMaxPriorityQueue = flagMaxPriorityQueue;
obj.numElements = 0;
obj.priorityList = {};
obj.valueList = {};
end
function insert(obj, priority, value)
% increase the size of the array if full
if obj.numElements > 0 && obj.numElements + 1 > numel( obj.priorityList )
% double the size of the array and copy stuff
obj.priorityList = cat(1, obj.priorityList, cell(obj.numElements, 1));
obj.valueList = cat(1, obj.valueList, cell(obj.numElements, 1));
end
obj.numElements = obj.numElements + 1;
obj.priorityList{ obj.numElements } = priority;
obj.valueList{ obj.numElements } = value;
obj.swim(obj.numElements);
end
function [priority, value] = pop( obj )
if obj.isEmpty()
error( 'called pop() on an empty priority queue' );
end
priority = obj.priorityList{1};
value = obj.valueList{1};
obj.exch(1, obj.numElements);
obj.numElements = obj.numElements - 1;
obj.sink(1);
obj.priorityList{ obj.numElements + 1 } = [];
obj.valueList{ obj.numElements + 1 } = [];
% halve the size of the arrays if they get one-quarter full
if obj.numElements > 0 && obj.numElements == floor( numel( obj.priorityList ) / 4 )
obj.priorityList( 2 * obj.numElements + 1 : end ) = [];
obj.valueList( 2 * obj.numElements + 1 : end ) = [];
end
end
function [flagEmpty] = isEmpty( obj )
flagEmpty = (obj.numElements == 0);
end
function [qSize] = size( obj )
qSize = obj.numElements;
end
function [priority, value] = peek( obj )
if obj.isEmpty()
error( 'requested max() of an empty priority queue' );
end
priority = obj.priorityList{1};
value = obj.valueList{1};
end
end
methods (Access = private)
function swim(obj, elPos)
while elPos > 1 && obj.compare(floor(elPos / 2), elPos)
obj.exch(floor(elPos / 2), elPos);
elPos = floor(elPos / 2);
end
end
function sink(obj, elPos)
while 2 * elPos <= obj.numElements
j = 2 * elPos;
if j < obj.numElements && obj.compare(j, j+1)
j = j + 1;
end
if ~obj.compare(elPos, j)
break;
end
obj.exch(elPos, j);
elPos = j;
end
end
function [blnCmpResult] = compare(obj, e1, e2)
if obj.flagMaxPriorityQueue
blnCmpResult = (obj.priorityList{e1} < obj.priorityList{e2});
else
blnCmpResult = (obj.priorityList{e1} > obj.priorityList{e2});
end
end
function exch(obj, e1, e2 )
temp = obj.priorityList{e1};
obj.priorityList{e1} = obj.priorityList{e2};
obj.priorityList{e2} = temp;
temp = obj.valueList{e1};
obj.valueList{e1} = obj.valueList{e2};
obj.valueList{e2} = temp;
end
end
end % classdef