Первый подход: с использованием tf.one_hot
и tf.boolean_mask
:
# shape = (?,1,3)
mask_idx = 1- tf.one_hot(idx,a.shape[1])
# shape = (?,3)
result = tf.boolean_mask(a,mask_idx[:,0,:])
# shape = (?,2,3)
result = tf.reshape(result,shape=(-1,a.shape[1]-1,a.shape[2]))
Второй подход: с использованием tf.map_fn
:
result = tf.map_fn(lambda x: tf.boolean_mask(x[0],1 - tf.one_hot(tf.squeeze(x[1]),a.shape[1]))
, [a,idx]
, dtype=tf.int32)
Пример:
import tensorflow as tf
a = tf.constant([[[1,2,3],[4,5,6],[7,8,9]],
[[9,8,7],[6,5,4],[3,2,1]],
[[0,8,0],[1,5,4],[3,1,1]]],dtype=tf.int32)
idx = tf.constant([[1],[0],[2]],dtype=tf.int32)
# First approach:
# shape = (?,1,3)
mask_idx = 1- tf.one_hot(idx,a.shape[1])
# shape = (?,3)
result = tf.boolean_mask(a,mask_idx[:,0,:])
# shape = (?,2,3)
result = tf.reshape(result,shape=(-1,a.shape[1]-1,a.shape[2]))
# Second approach:
result = tf.map_fn(lambda x: tf.boolean_mask(x[0],1 - tf.one_hot(tf.squeeze(x[1]),a.shape[1]))
, [a,idx]
, dtype=tf.int32)
with tf.Session() as sess:
print(sess.run(result))
# print
[[[1 2 3]
[7 8 9]]
[[6 5 4]
[3 2 1]]
[[0 8 0]
[1 5 4]]]
Интервьюер, возможно, хотел получить ответ примерно так:
i = i + 1
должен будет загрузить значениеi
, добавить единицу к его, а затем сохраните результат обратно вi
. Напротив,++ i
может просто увеличивать значение с помощью одной инструкции ассемблера, поэтому теоретически это могло бы быть более эффективным. Однако большинство компиляторов оптимизируют разницу, и сгенерированный код будет точно таким же.
FWIW, тот факт, что вы знаете, как смотреть на сборку, делает вас лучшим программистом, чем 90% людей, которые у меня были брать интервью на протяжении многих лет. Утешайте себя тем, что вам не придется работать с бестолковым неудачником, который брал у вас интервью.
Похоже, вы были правы, а они ошибались. У меня была аналогичная проблема на собеседовании, когда я дал правильный ответ, который посчитали неправильным.
Я уверенно спорил со своим интервьюером, который явно обиделся на мою наглость. Я не получил работу, но, опять же, работать с кем-то, кто "знает все", тоже было бы нежелательно.
Вы, наверное, правы. Наивный компилятор мог бы сделать:
++i to inc [ax]
и
i = i + 1 to add [ax], 1
, но любой наполовину разумный компилятор просто оптимизирует добавление 1 к первой версии.
Все это предполагает, что соответствующая архитектура имеет инструкции inc и add (как это делает x86).
Чтобы защитить интервьюера, контекст решает все. Какой тип я? Мы говорим о C или C ++ (или о каком-то другом языке, подобном C)? Вам дали:
++i;
i = i + 1;
или был еще контекст?
Если бы меня спросили об этом, мой первый ответ был бы "Я изменчив?" Если да, то разница огромна. Если нет, то разница небольшая и смысловая, но с практической точки зрения нет. Доказательством этого является различие в дереве синтаксического анализа и окончательное значение сгенерированных поддеревьев.
Похоже, вы правильно поняли прагматическую сторону, но ошиблись с семантической / критической стороной мышления.
Напасть на интервьюера. (без контекста), мне бы хотелось задаться вопросом, в чем была цель вопроса. Если бы я задал вопрос, я бы хотел использовать его, чтобы узнать, знает ли кандидат тонкие семантические различия, как создать дерево синтаксического анализа, как мыслить критически и так далее, и так далее. Я обычно задаю респондентам вопрос C, который почти каждый кандидат ошибается - и это намеренно. На самом деле меня не волнует ответ на вопрос, меня волнует путешествие, которое я предприму с кандидатом , чтобы достичь понимания, которое говорит мне гораздо больше, чем о правильном / неправильном в пустяковом вопросе .
В C ++ это зависит от того, является ли i
целым числом или объектом. Если это объект, вероятно, будет создан временный экземпляр.
контекст является здесь главным, потому что при оптимизированной сборке выпуска компилятор оптимизирует i ++, если он доступен для простого [inc eax]. тогда как что-то вроде int some_int = i ++ необходимо сохранить значение i в some_int FIRST и только затем увеличивать i.