Calculating h-index - c

I need to calculate the h-index from a list of publications i stored in a tree.
What i did is traversing the tree in decrescent order obtaining a list of position-number of citations
it looks like:
line 1 10
line 2 5
line 3 4
line 4 0
I should stop at line 3 and return 3. The problem is with the examples given and in this case
line 1 4
line 2 0
line 3 0
it stops at 2 because 4>1 but 0>3 is false. It should return 1 instead. Can you explain me why? I know it's more like a mathematician question, but after that i could need to re-implement it if something is deeply wrong.
Here is the code
int index_h_calc(rbtree_node n, int *i){
if (n == NULL) {
fputs("<empty tree>\n", stdout);
return 0;
}
if (n->right != NULL)
index_h_calc(n->right,i);
graduat *grad;
grad=n->value;
if(DEBUG)
printf("linea %d %d %s\n ",*i,(int)grad->tot,grad->name);
if(*i+1>=(int)grad->tot) {
return *i;
} else
*i+=1;
if (n->left != NULL)
index_h_calc(n->left,i);
return *i;
}

This has several solutions on github, eg in Ruby, equivalent to your n is citePages and being the h-index calculated
function h_index(){
var hArray = new Array();
var x = 0;
for(var i = 0; i < citePages.length; i++){
var citeArray = citePages[i];
for(var j = 0; j < citeArray.length; j++){
// The multiplication by one is a hack to convert the string type into a numerical type
hArray[x++] = citeArray[j]*1;
}
}
hArray.sort(sortNumber);
//alert(hArray);
for(var i = 0; i < hArray.length; i++){
if(i > hArray[i]){
return hArray[i-1];
}
}
}
previous function -
function getCitationCount(responseText){
if (responseText == null){
_gel("sContent").innerHTML = "<i>Invalid data.</i>";
alert("There is no data.");
return;
}
var cite_exists = 1;
var cite_str_len = 14;
var len_of_Cite_by_str = 9;
var citeArray = new Array();
for(var i = 0; cite_exists > 0; i++)
{
cite_exists = responseText.search('Cited by');
if(cite_exists == -1){
//alert("No more citations for given Author!");
//return;
}else{
var tmp_string = responseText.substr(cite_exists, cite_str_len);
var end = (tmp_string.indexOf("<")-len_of_Cite_by_str);
citeArray[i] = tmp_string.substr(len_of_Cite_by_str, end);
publications++;
responseText = responseText.substr(cite_exists+cite_str_len, responseText.length);
}
}
return citeArray;
}
If this doesn't provide a solution then the problem to be verifiable - so we really need example data, eg a jsfiddle of typical data stating what result is expected in each case, given that this is a mathematical rather than coding question and can only be tested with a populated complex data structure.

Perhaps I am missing some subtlety, but isn't the answer just to subtract one from the line number? That is, if i is the line number and n is the number of citations, you traverse the tree until you find a line with n < i and then return the h-index as i - 1.

Related

how to find near value?

Iam trying to see if there is a shorter method in being able to find the nearest value in a linear search algorithm if the value you are searching for doesnt exist,without using any searching / sorting built in methods. Thank you.
Here is my current method below,although my attempt seems inefficent.
(iam assuming the array is already sorted)
public void LinearSearchNearest(int[] data, int target, string dataname)
{
Console.WriteLine(dataname + ": ");
int StepsNearest = 0;
int n = data.Length;
StepsNearest++;
// Check for corner cases (check the value is actually within range of the array)
if (target < data[0])
{
Console.WriteLine($"Closest value : {data[0]}, Position : {1} (value outside of array bounds) ");
Console.WriteLine($"Num of Steps is : {StepsNearest}");
return;
}
if (target > data[n - 1])
{
Console.WriteLine($"Closest value : {data[n - 1]}, Position : {n} (value outside of array bounds) ");
Console.WriteLine($"Num of Steps is : {StepsNearest}");
return;
}
int closestVal = 0;
int position = 0;
int found = 0;
int targetCount = 0;
Console.Write("Value is at positions : ");
for (int i = 0; i < data.Length; i++)
{
StepsNearest++;
if (data[i] == target)
{
targetCount++;
found++;
Console.Write($"{i + 1}, ");
}
else
{
StepsNearest++;
// Compare closest value currently to new value to see which one is closer to target
long along = data[i];
long blong = closestVal;
long clong = target;
var distanceA = Math.Abs(clong - along);
var distanceB = Math.Abs(clong - blong);
if (distanceA < distanceB)
{
closestVal = data[i];
position = i + 1;
}
}
}
// Check if target value was found or not in the array given
string result = (found == 0) ? $"Closest value : {closestVal}, Position : {position} " +
$"\nNum of Steps is : {StepsNearest}" : $"\nNum of Steps is : {StepsNearest}";
Console.WriteLine(result);
}
UPDATE CODE
public void LinearSearchNearest(int[] data, int target, string dataname)
{
Console.WriteLine(dataname + ": ");
StepsNearest = 0;
int closestVal = 0;
int position = 0;
int found = 0;
int minDistance = int.MaxValue;
Console.Write("Value is at positions : ");
for (int i = 0; i < data.Length; i++)
{
StepsNearest++;
if (data[i] == target)
{
found = 1;
Console.Write($"{i + 1}, ");
}
else
{
StepsNearest++;
// Compare closest value currently to new value to see which one is closer to target
int distance = System.Math.Abs(data[i] - target);
if (distance < minDistance)
{
minDistance = distance;
closestVal = data[i];
position = i + 1;
}
}
}
// Check if target value was found or not in the array given
string result = (found == 0) ? $"Closest value : {closestVal}, Position : {position} " +
$"\nNum of Steps is : {StepsNearest}" : $"\nNum of Steps is : {StepsNearest}";
Console.WriteLine(result);
}
If the array is assumed to be sorted as you said in the comments, then you could just walk through the array until you find a value that's equal to or larger than the target. If the value is equal, then of course we'd return that index.
If the value is larger, then we compare the difference of this value and the target with the difference of the previous value and the target, and return the index of the value with the smallest difference.
If we never find an equal or larger value, then we return the last index:
public int GetIndexOfNearest(int[] data, int target)
{
if (data == null) throw new ArgumentNullException(nameof(data));
if (target <= data[0]) return 0;
if (target >= data[data.Length - 1]) return data.Length - 1;
for (int i = 0; i < data.Length; i++)
{
// If we find a match, return that index
if (data[i] == target) return i;
// If this value is greater than the target then we either
// return this index or the previous index, depending
// on which one has the smallest diff with the target
if (data[i] > target)
{
var thisDiff = Math.Abs(data[i] - target);
var prevDiff = Math.Abs(data[i - 1] - target);
if (thisDiff < prevDiff) return i;
else return i - 1;
}
}
// We should never get here, since this is the case where all the items are smaller
// than the target, which we checked in the third line, but the compiler requires it
return data.Length - 1;
}
You can do all in one iteration. This will either find the first exact match or the nearest element to the search value in an UNORDERED array. If there are multiple elements with the same distance to the search value, it will find the first one.
let values = [...]; //your value list
let search = ...; //your value to search
let index = 0; //index where element is found
for (let i = 0; i < values.length; i++) {
// if the current element is an exact match, set the index to i
// and break the loop
if (values[i] == search) {
index = i;
break;
}
// else if current element is "nearer" to the searchvalue than
// the previously remembered, remember the current index
else if (abs(values[i] - search) < abs(values[index] - search)) {
index = i;
}
}
If you assume, that your array is already sorted you could do it as follows
let values = [...]; //your value list
let search = ...; //your value to search
let index = 0; //index where element is found
for (let i = 0; i < values.length; i++) {
// if the current element is an exact match, set the index to i
// and break the loop
if (values[i] == search) {
index = i;
break;
}
// while the current value is less then the search value,
// just remember the index
else if (values[i] < search) {
index = i;
}
// if the current value is greater then the search value
// check whether the previous or the current element is nearer to the search value
else if (values[i] > search) {
index = abs(search - values[i]) < abs(search - values[index])
? i
: index;
break;
}
}
Shorter? Maybe. What I have to offer is (hopefully) faster.
Let's summarize what you are looking for:
IN: Array of int, sorted (ascending order)
IN: target int value.
OUT: Array of all indices with values with minimal distance to target.
Given, that the data contains sorted data allows us to pick an algorithm, which performs more quickly than linear search. Linear search (O(N)) would be our only choice were the data in the array not sorted.
But as data is sorted, we can do binary search, which has O(log n) runtime.
With the help of binary search, we can find 1 or 2 candidates, which have the minimal distance to target.
Then, it is just a matter of looping towards the left and towards the right as long as there are values with that same minimal distance as our minimal candidate had.
A wall of code says more than 1000 words, right? Here we go:
using System;
using System.Linq;
using System.Collections.Generic;
namespace nearest
{
class Program
{
static int BinarySearchClosest( int[] data, int target, int left, int right)
{
if (right < left)
throw new ArgumentException(nameof(right));
if ((right - left) < 2)
return left;
var mid = left + (right - left) / 2;
if ( target > data[mid])
return BinarySearchClosest(data,target, mid, right);
else
return BinarySearchClosest(data,target, left, mid);
}
static int IndexOfClosestExistingValue( int[] data, int target) {
if (null == data) throw new ArgumentNullException(nameof(data));
if (0 == data.Length)
return -1;
// 1.Do a binary search to get within the same zip code of what
// we are looking for.
var ballpark = BinarySearchClosest(data, target, 0, data.Length);
// 2. we are close. The real minimum distance is either
// Math.Abs(data[ballpark]-target) or
// (Math.Abs(data[ballpark+1]-target) IFF (ballpark+1) < data.Length).
var minDist = Math.Abs(data[ballpark]-target);
var imin = ballpark;
if (((imin+1) < data.Length) && (Math.Abs(data[imin+1]-target) < minDist)) {
minDist = Math.Abs(data[imin+1]-target);
imin = imin + 1;
}
return imin;
}
static int[] IndicesOfClosestExistingValues( int[] data, int target)
{
List<int> result = new List<int>();
var imin = IndexOfClosestExistingValue(data, target);
if (imin >= 0) {
var minDist = Math.Abs(data[imin]-target);
result.Add(imin);
// Add equally good matches to the left of imin to the result.
for (var i = imin - 1;
i >= 0 && Math.Abs(data[i]-target) == minDist; i--) {
result.Add(i);
}
// Add equally good matches to the right of imin to the result.
for (var i = imin +1;
i < data.Length && Math.Abs(data[i]-target) == minDist; i++) {
result.Add(i);
}
}
return result.ToArray();
}
internal struct TestCase {
internal int[] data;
internal int target;
internal int[] expected;
}
static string TestCaseToString( TestCase tc) {
var sb = new System.Text.StringBuilder();
sb.AppendFormat(
"TestCase{{ data = {{{0}}}, target = {1}, expected = {{{2}}}}}",
string.Join(", ", tc.data),
tc.target,
string.Join(", ", tc.expected));
return sb.ToString();
}
static void Main(string[] args)
{
TestCase[] testCases =
{ new TestCase{
data = new int[]{},
target = 42,
expected = new int[]{} }, // data.Length == 0
new TestCase{
data = new int[]{1},
target = 42,
expected = new int[]{0} }, // data.Length == 1
new TestCase{
data = new int[]{1, 41, 45, 99},
target = 42,
expected = new int[]{1} }, // somewhere in the middle
new TestCase{
data = new int[]{100,101,102},
target = 42,
expected = new int[]{0} }, // far left
new TestCase{
data = new int[]{1,2,3},
target = 42,
expected = new int[]{2} }, // far right
new TestCase{
data = new int[]{1,1,1,1},
target = 42,
expected = new int[]{3,2,1,0} }, // multiple matches left
new TestCase{
data = new int[]{100,100,100,100},
target = 42,
expected = new int[]{0,1,2,3} }, // multiple matches right
new TestCase{
data = new int[]{41,41,41,41,43,43,43,43},
target = 42,
expected = new int[]{3,2,1,0,4,5,6,7} }, // multiple matches both sides
new TestCase{
data = new int[]{4,6},
target = 5,
expected = new int[]{0,1} } // multiple disjoint matches
};
int failCounter = 0;
int testCaseIndex = 0;
foreach ( var tc in testCases ) {
try {
int[] actual =
IndicesOfClosestExistingValues(tc.data, tc.target);
bool verdict = Enumerable.SequenceEqual(actual, tc.expected);
if (false == verdict)
failCounter++;
Console.WriteLine(
"{1}: {0}, actual = {{{2}}}",
TestCaseToString(tc),
verdict == true ? "OK" : "FAILED",
string.Join(", ", actual));
}
catch (FormatException) {
Console.WriteLine("{0}: FAULTED", testCaseIndex);
}
catch (ArgumentNullException) {
Console.WriteLine("{0}: FAULTED (argument null)", testCaseIndex);
}
finally {
testCaseIndex++;
}
}
Console.WriteLine("Done. ({0} tests failed.)", failCounter);
}
}
}
I did not use C# in many years and if you want to explore algorithms without a lot of lines of code and typing, I strongly recommend to use a more terse language (unless you really want to learn C#). F# is an attractive alternative as it uses the same run time, has the same default libraries and is much more easy on your fingers.

How do I get the integer method "guess" to go into another method as an array?

else {
masterNum[3] = guess % 10; //checks integers in their respective positions
masterNum[2] = ((guess - guess%10)/10)%10;
masterNum[1] = ((guess - guess % 100)/100)%10;
masterNum[0] = (guess - guess % 1000)/1000;
masterDigit(guess, masterNum);
}
//}
//This method determines the total number of correct digits but not
//necessarily in the correct position
public static int masterDigit (int [] guess,int [] code) //int [] guess
{
int i,j,k,number;
int [] tempGuess = new int [4]; //an array to hold a copy of a code
boolean found;
number = 0;
for(k=0; k<4; k++) //copies code to tempGuess so code
//doesn't get changed (you can't just assign code to tempGuess)
tempGuess[k] = code[k];
for(i = 0; i < 4; i++)
{
j=0;
found = false;
while(j < 4 && found == false) // a while loop instead of a
// for loop so duplicates are only counted once
{
if(guess[i] == tempGuess[j])
{
found = true;
tempGuess[j] = -1; // fills up tempGuess with an impossible
// value so that index only gets
// counted once
number++;
}
j++;
}
}
return number;
}
This code is for a Mastermind game with integers. Upon running through the compiler, there is an error saying that integer "guess" cannot be converted to an array. How can I get my guess (defined as an integer scanner console) to go into this method that will check which numbers are correct?

The longest sub-array with switching elements

An array is called "switching" if the odd and even elements are equal.
Example:
[2,4,2,4] is a switching array because the members in even positions (indexes 0 and 2) and odd positions (indexes 1 and 3) are equal.
If A = [3,7,3,7, 2, 1, 2], the switching sub-arrays are:
== > [3,7,3,7] and [2,1,2]
Therefore, the longest switching sub-array is [3,7,3,7] with length = 4.
As another example if A = [1,5,6,0,1,0], the the only switching sub-array is [0,1,0].
Another example: A= [7,-5,-5,-5,7,-1,7], the switching sub-arrays are [7,-1,7] and [-5,-5,-5].
Question:
Write a function that receives an array and find its longest switching sub-array.
I would like to know how you solve this problem and which strategies you use to solve this with a good time complexity?
I am assuming that the array is zero indexed .
if arr.size <= 2
return arr.size
else
ans = 2
temp_ans = 2 // We will update ans when temp_ans > ans;
for i = 2; i < arr.size ; ++i
if arr[i] = arr[i-2]
temp_ans = temp_ans + 1;
else
temp_ans = 2;
ans = max(temp_ans , ans);
return ans;
I think this should work and I don't think it needs any kind of explanation .
Example Code
private static int solve(int[] arr){
if(arr.length == 1) return 1;
int even = arr[0],odd = arr[1];
int start = 0,max_len = 0;
for(int i=2;i<arr.length;++i){
if(i%2 == 0 && arr[i] != even || i%2 == 1 && arr[i] != odd){
max_len = Math.max(max_len,i - start);
start = i-1;
if(i%2 == 0){
even = arr[i];
odd = arr[i-1];
}else{
even = arr[i-1];
odd = arr[i];
}
}
}
return Math.max(max_len,arr.length - start);
}
It's like a sliding window problem.
We keep track of even and odd equality with 2 variables, even and odd.
Whenever we come across a unmet condition, like index even but not equal with even variable and same goes for odd, we first
Record the length till now in max_len.
Reset start to i-1 as this is need incase of all elements equal.
Reset even and odd according to current index i to arr[i] and arr[i-1] respectively.
Demo: https://ideone.com/iUQti7
I didn't analyse the time complexity, just wrote a solution that uses recursion and it works (I think):
public class Main
{
public static int switching(int[] arr, int index, int end)
{
try
{
if (arr[index] == arr[index+2])
{
end = index+2;
return switching(arr, index+1, end);
}
} catch (Exception e) {}
return end;
}
public static void main(String[] args)
{
//int[] arr = {3,2,3,2,3};
//int[] arr = {3,2,3};
//int[] arr = {4,4,4};
int[] arr = {1,2,3,4,5,4,4,7,9,8,10};
int best = -1;
for (int i = 0; i < arr.length; i++)
best = Math.max(best, (switching(arr, i, 0) - i));
System.out.println(best+1); // It returns, in this example, 3
}
}
int switchingSubarray(vector<int> &arr, int n) {
if(n==1||n==2) return n;
int i=0;
int ans=2;
int j=2;
while(j<n)
{
if(arr[j]==arr[j-2]) j++;
else
{
ans=max(ans,j-i);
i=j-1;
j++;
}
}
ans=max(ans,j-i);
return ans;
}
Just using sliding window technique to solve this problems as element at j and j-2 need to be same.
Try to dry run on paper u will surely get it .
# Switching if numbers in even positions equal to odd positions find length of longest switch in continuos sub array
def check(t):
even = []
odd = []
i = 0
while i < len(t):
if i % 2 == 0:
even.append(t[i])
else:
odd.append(t[i])
i += 1
if len(set(even)) == 1 and len(set(odd)) == 1:
return True
else:
return False
def solution(A):
maxval = 0
if len(A) == 1:
return 1
for i in range(0, len(A)):
for j in range(0, len(A)):
if check(A[i:j+1]) == True:
val = len(A[i:j+1])
print(A[i:j+1])
if val > maxval:
maxval = val
return maxval
A = [3,2,3,2,3]
A = [7,4,-2,4,-2,-9]
A=[4]
A = [7,-5,-5,-5,7,-1,7]
print(solution(A))

AS3: How to check if a value already exists in the Array before adding with FOR loop?

I believe is something simple but obviously not simple enough :). Any ideas how to check if a value already exists in the Array before adding the value using FOR loop?
I have this so far and it doesn't work as I want to because the Array can contain duplicate values!
var n:int = 5;
var cnt:int;
for (var i = 0; i < n; i++)
{
cnt = randomThief();
for (var a = 0; a < loto5.length; a++)
{
if (loto5[i] == cnt)
{
loto5[i] = cnt;
}
}
}
You can use the indexOf() method of the Array class to check if the value exists like this :
var index:int = loto5.indexOf(cnt);
indexOf() returns a -1, if the value doesn't exist. Here is an example of how to do a check :
if (loto5.indexOf(cnt) >= 0)
{
// do something
}
for (var a = 0; a < loto5.length; a++)
{
cnt = randomThief();
if (loto5.indexOf(cnt) == -1) //if cnt isn't in array do ...
{
trace (cnt+" is not in Array");
loto5[a] = cnt;
}
}
Works, simple and beauty :)

input an array output bigger array related to input

suppose I have a arrays from each i want to produce b these are just examples
a=[4]=> b=[0,4]
a=[3,1]=>b=[0,3,3,4]
a=[2,2]=>b=[0,2,2,4]
a=[2,1,1]=>b=[0,2,2,3,3,4]
a=[3,4,2,5]=>b=[0,3,3,7,7,9,9,14]
I mean when getting 4 it should produce from 0 and then add it to it's content for example 4
or in a[2,1,1] first it will produce 0 and then it see that the next one in a is 1 so after again producing it it will compute 2+1 and assign it.so the output always will be twice size of the input.
i want a pseudo code for it my problem is that when it will repeat I can not write it.
I used JavaScript like syntax.
var a = new Array(3,4,2,5);
var b = new Array();
var bArrayIndex = 0;
b[bArrayIndex] = 0;
bArrayIndex++;
for(i = 0; i < a.length; i++) {
b[bArrayIndex] = b[bArrayIndex-1] + a[i];
if(i < a.length - 1) {
b[bArrayIndex+1] = b[bArrayIndex];
}
bArrayIndex+=2;
}
for(i = 0; i < b.length; i++) {
document.write(b[i] + " ");
}

Resources